Skip to main content

Overview

Live Activities are the core user-facing feature of Sightscreen. When a user follows a live match, the app starts a Live Activity that shows ball-by-ball scoring on the Lock Screen and Dynamic Island. All content is driven by backend APNs pushes — the app renders what it receives. The Live Activity system is managed by three dedicated managers, composed behind a LiveActivityService facade.

Three-manager architecture

The original monolithic LiveActivityService has been split into three focused managers, each owning a distinct concern.

LiveActivityTokenManager

Owns everything related to push tokens — observation, deduplication, and backend registration.

LiveActivityLifecycleManager

Owns the creation, adoption, observation, and teardown of Live Activity instances.

FollowManager

Owns the user’s follow/unfollow intent and syncs it with the backend.
The three managers share no mutable state directly. LiveActivityService (the facade) coordinates between them. If you need to change how managers interact, modify the facade — not the managers themselves.

Live Activity lifecycle

Start routes

There are two ways a Live Activity can start:
1

User follow (local creation)

User taps the bell icon. FollowManager records the follow. LifecycleManager calls Activity.request() with pushType: .token. TokenManager begins observing the update token and POSTs it to the backend.
2

Push-to-start (remote creation)

Backend sends a push-to-start APNs notification. The system creates the Live Activity without the app running. On next launch (or in background), LifecycleManager.adoptPushStartedActivity() claims the activity via Activity.activityUpdates. TokenManager then observes and registers the update token.

End reasons

A Live Activity can end for four reasons:

Token management

Three token types

Token rotation

iOS can rotate tokens at any time. TokenManager handles this by:
  1. Continuously observing the async stream (not reading a snapshot)
  2. Comparing each received token against the cached last-sent value
  3. Only POSTing to backend when the token actually changes

Push-to-start token deduplication

The system may fire pushToStartTokenUpdates twice for the same token value. TokenManager deduplicates by caching and comparing before sending.
Never try to read activity.pushToken synchronously after creation. The token is not available immediately. Always use the pushTokenUpdates async stream.

Push-to-start flow

1

Pre-follow

The user follows a match before it goes live. FollowManager records the follow and TokenManager registers the push-to-start token with the backend.
2

Backend triggers start

When the match goes live, the backend sends a push-to-start APNs payload using the registered push-to-start token.
3

System creates activity

iOS creates the Live Activity in the background. The app does not need to be running.
4

Adoption

LifecycleManager detects the new activity via Activity.activityUpdates and calls adoptPushStartedActivity() to begin managing it.
5

Token registration

TokenManager observes the update token for the adopted activity and POSTs it to the backend, enabling subsequent content updates.
Push-to-start allows the backend to launch a Live Activity even if the user has not opened the app since following the match. This is the primary start path for pre-followed matches.

Stale activity cleanup

If a Live Activity receives no content-state push for 30 minutes, LifecycleManager considers it stale and ends it. This prevents users from seeing outdated scores (e.g., during a backend outage or if the match is abandoned). The stale check runs:
  • On app foreground (via ScenePhase observation)
  • When restoring activities on relaunch
  • Periodically while the app is active
The 30-minute threshold is a local safety net. The backend should always send an explicit end push when a match completes. Stale detection catches edge cases where that push was lost.

Required presentations

Every Live Activity must implement 6 mandatory presentations. Missing any of these causes a build-time or App Store review rejection.
The compact leading and trailing views appear together when only one Live Activity is running. If multiple are active, iOS picks one for the Minimal presentation and shows the other in Compact.

Content state contract

The backend sends APNs pushes that update the Live Activity content state. The iOS app decodes and renders — no transformation.

APNs push types

Key event handling

Certain events (wickets, milestones) are assigned priority 10 (relevance-score: 10) in the APNs push. This ensures iOS gives them prominence in the Dynamic Island with haptic feedback and expanded presentation.

API endpoints


State management summary