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 aLiveActivityService facade.
Three-manager architecture
The original monolithicLiveActivityService 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.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:
- Continuously observing the async stream (not reading a snapshot)
- Comparing each received token against the cached last-sent value
- Only POSTing to backend when the token actually changes
Push-to-start token deduplication
The system may firepushToStartTokenUpdates twice for the same token value. TokenManager deduplicates by caching and comparing before sending.
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.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
ScenePhaseobservation) - 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.