ActivityKit

RSS for tag

Help people keep track of tasks and events that they care about with Live Activities on the Lock Screen, the Dynamic Island, and in StandBy.

Posts under ActivityKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

Live Activities: no minute-granularity self-updating countdown text; custom DiscreteFormatStyle types fail to decode in the system renderer
Summary There is no supported way for a Live Activity to display a self-updating countdown at minute granularity in the form transit riders expect — a bare "7 min" that ticks to "6 min" — even though Apple's own apps (Timer in the Dynamic Island, Maps ETA) display exactly this form. The API that should make this possible — Text(_ input: TimeDataSource<Date>, format:) with a custom DiscreteFormatStyle (added in iOS 18) — compiles and archives, but the rendered activity fails at decode time in the system renderer, so every region of the Live Activity displays grey placeholder boxes. What I'm building An NYC subway departures app. The app's design language everywhere (in-app, home screen widgets via baked timeline entries) is "7 min" / "Now". Real-world fidelity is minute-level: riders don't think in mm:ss. The Live Activity is the only surface that cannot match this design, because it can only use self-updating text between content updates, and none of the built-in live formats produce it. Built-in options and why each falls short Text(timerInterval:countsDown:) — mm:ss only; no minute-granularity mode (this is FB23091094). Also reserves maximum width (FB23091111). Text(date, style: .relative) — always appends a second unit ("7 min, 30 sec") and counts up ambiguously (unsigned) after the date passes. .reference(to:allowedFields:maxFieldCount:) (iOS 18) — closest usable option, but only spelled-out wide units with a mandatory preposition: "in 7 minutes". No abbreviated/narrow width option exists on SystemFormatStyle.DateReference. .offset(to:) (iOS 18) — measures time since the anchor, so an upcoming departure renders as a negative value ("−7 minutes"); inverted for countdown use, and also wide-units only. The bug: custom DiscreteFormatStyle fails to decode in the renderer A custom format style solves this completely — mine rendered exact "7 min"/"Now" strings and, by holding the full departure list, even advanced to the next train the moment one departed, all without waking the app: @available(iOS 18.0, *) struct TrainCountdownFormat: DiscreteFormatStyle { var departures: [Date] var rank: Int // 0 = closest upcoming train var fullText: Bool // "7 min" vs "7m" func format(_ now: Date) -> String { let upcoming = departures.filter { $0 > now }.sorted() guard rank < upcoming.count else { return "—" } let totalSeconds = Int(upcoming[rank].timeIntervalSince(now)) if totalSeconds < 60 { return "Now" } let minutes = totalSeconds / 60 return fullText ? "\(minutes) min" : "\(minutes)m" } func discreteInput(after input: Date) -> Date? { departures.compactMap { departure -> Date? in let seconds = departure.timeIntervalSince(input) guard seconds > 0 else { return nil } let intoMinute = seconds.truncatingRemainder(dividingBy: 60) return input.addingTimeInterval(intoMinute > 0 ? intoMinute : 60) }.min() } func discreteInput(before input: Date) -> Date? { departures.compactMap { departure -> Date? in let seconds = departure.timeIntervalSince(input) guard seconds > 0 else { return departure < input ? departure : departure.addingTimeInterval(-60) } let intoMinute = seconds.truncatingRemainder(dividingBy: 60) return input.addingTimeInterval(intoMinute - 60) }.max() } } // In the ActivityConfiguration views: Text(.currentDate, format: TrainCountdownFormat(departures: dates, rank: 0, fullText: true)) This compiles and the activity is created, but every presentation (compact trailing, expanded, lock screen) renders as grey placeholder boxes. The console shows the archive being rejected at decode time in the renderer process: WidgetRenderer_Activities: (WidgetRenderer) [com.apple.chrono:activityRendererClient-verbose] Failed to return view entry from archive for view model with tag dynamicIsland-compactTrailing with error: SwiftUI.AnyCodable<...SafelyCodableRequirement>...Errors.noType(mangledName: "7SwiftUI18TimeDataFormattingO10ResolvableVy_AA0cD6SourceVAAE11DateStorageOy10Foundation0H0V_G 27NowDepartingWidgetExtension10$1030be9a0yXZ20TrainCountdownFormatV G") i.e. the archived TimeDataFormatting.Resolvable wrapper references a type defined in the app's widget extension, which the system renderer cannot look up. Nothing in the DiscreteFormatStyle or Text(_:format:) documentation states that only system-defined format styles are renderable in Live Activities, and there is no compile-time or runtime diagnostic surfaced to the developer — the activity just renders blank. Requests (either would unblock this) Support custom DiscreteFormatStyle types in Live Activity rendering (e.g. by evaluating the format in the extension's process when pre-rendering discrete frames), or at minimum document the limitation and fail loudly instead of rendering placeholder boxes. Add minute-granularity and unit-width options to the built-in live formats: a showsSeconds/fields option on Text(timerInterval:) (FB23091094), and/or a units-width option (abbreviated/narrow) plus a "bare duration, no preposition, countdown sign convention" variant on SystemFormatStyle.DateReference / DateOffset. Steps to reproduce Create a Live Activity whose views use Text(.currentDate, format:) with any custom DiscreteFormatStyle (sample above). Start the activity; background the app. Observe the Dynamic Island and lock screen render grey placeholder boxes for every region, and WidgetRenderer_Activities logs Errors.noType for each view model tag. Expected: the custom format renders and updates at the boundaries reported by discreteInput(before:/after:), as it does for the system styles. Actual: decode failure in the renderer; entire activity renders as placeholders. Environment Xcode 27.0 (27A266a) iOS 27.0 simulator, iPhone 18 Pro (also applies to iOS 18+ per API availability) Widget extension deployment target: iOS 17.6 Related reports: FB23091094, FB23091111, forum thread https://developer.apple.com/forums/thread/834337
0
0
17
8h
Inconsistencies with activityBackgroundTint when a device switches between light and dark modes
While the activityBackgroundTint modifier is intended to set the background color of a Live Activity, it often fails to dynamically update, leaving the activity with an incorrect background. Replacing it with ZStack { Color(.background) .... } solves the problem, but this is a workaround. The activityBackgroundTint modifier is still needed, at a minimum, so that the "Allow Live Activity for the app" extension does not have the default color.
Topic: Design SubTopic: General Tags:
3
1
601
8h
Screen capture of other apps without the broadcast picker — any public API?
Two quick questions about ReplayKit on iOS: Is there any public API or entitlement that lets an app capture the screen while another app is in the foreground without presenting RPSystemBroadcastPickerView each session? Is custom-content Picture-in-Picture (AVSampleBufferDisplayLayer with AVPictureInPictureController) considered acceptable for a non-video status overlay, or is Live Activities the intended surface for that? Thanks.
0
0
262
4d
AlarmKit alarms fire late (or not until you wake up the iPhone)
Hey all, I've submitted a couple Feedback reports on this (FB22887867 on iOS 26 and FB24483266 on iOS 27), but wanted to share here for 1. validation that I'm not the only one experiencing this issue and 2. ask for ideas or experience with potential workarounds. The issue is that AlarmKit alarms, even when properly configured and scheduled from an app, will intermittently fire late, or not fire at all until the iPhone is woken up. For example, you might create an AlarmKit alarm with a relative schedule for 6:00am, then lock your iPhone before bed. When 6:00am passes, nothing happens. Then, at 6:13am it fires (with the full screen alert, audio and haptics) Or, you might wake up at 6:53am, notice that it didn't fire, tap the screen on your iPhone, the Lock Screen displays for about a second, then all of a sudden, the AlarmKit alert presents (with the full screen alert, audio and haptics). The issue has been present from iOS 26.0 up through the iOS 27.0 RC. I'm fairly confident that this is not a configuration issue. I've reproduced it using the WWDC 25 AlarmKit sample code and if you read from AlarmManager.shared.alarms, these alarms show up as expected: with a scheduled state and the correct times. The issue seems to be more common overnight, when the iPhone has been asleep for a while. It's less common on my personal iPhone but occurs probably once out of every 3 to 5 alarms on my test iPhones (which have much less interaction and background activity etc.). Of our app's few thousand daily users, we get complaints at least once a day. I've dropped a few sysdiagnose reports into Claude. In every instance, it claims that when the alarm was scheduled, mobiletimerd successfully registered an XPC wake-up for the alarm. However, during a completely unrelated event overnight (ex: a wifi packet), launchd drops the scheduled wake-up and nothing re-schedules it. So when 6:00am rolls around, nothing wakes up the iPhone to let the alarm fire. On days when it fires late, it's simply because another unrelated event (ex: a wifi packet) woke up the iPhone while the late alarm was queued. Looking forward to hearing your thoughts. Thank you.
1
0
119
5d
ActivityKit: sub-4KB JSON content-state exceeds size limit after numeric reserialization
I've filed FB24763792 about numeric JSON reserialization and the Live Activity content-state size limit. A compact JSON content-state can be below 4,096 bytes but expand beyond that limit when Foundation parses and reserializes its numbers. Here is an entirely synthetic Foundation reproduction: import Foundation let row = #"{"a":1.91,"b":1.91}"# let rows = Array(repeating: row, count: 100).joined(separator: ",") let input = Data("{"sequence":1,"readings":[(rows)]}".utf8) let object = try JSONSerialization.jsonObject(with: input) let output = try JSONSerialization.data(withJSONObject: object, options: []) print(input.count, output.count) On macOS 26.6.2 and the iOS 26.5 simulator, this prints 2027 4827. Foundation writes 1.91 as 1.9099999999999999. Change both values to 1.95 and it prints 2027 2027. In a separate local ActivityKit test, we passed the Foundation-reserialized data through a Decimal-based Codable state that preserved the expanded byte count: The 1.95 control remained at 2,027 bytes and applied successfully. The 1.91 case expanded to 4,827 bytes and was rejected with "Payload maximum size exceeded." The activity retained its previous state. We also tested the exact boundary: a 4,096-byte encoded dynamic state applied, while 4,097 bytes was rejected. Static attributes did not count toward that tested local-update boundary. This investigation began with remote Live Activities remaining stale while APNs returned HTTP 200 for dispatched updates. The device logged "Error extracing payload from incoming message" (spelling as logged). We are confident numeric expansion is the mechanism behind our issue. The tests above reproduce expansion and rejection locally; they do not replay an exact captured failed remote push. The ContentState documentation specifies a 4KB limit but doesn't make remote JSON normalization clear: https://developer.apple.com/documentation/activitykit/activityattributes/contentstate Questions for Apple: At what stage is remote content-state size measured? Can internal reserialization preserve compact numeric representations, or can the limit use the supplied content-state bytes? Can rejected incoming updates expose the underlying size error and measured byte count? The synthetic reproducer and a simulator diagnostic collected immediately after the local rejection are attached to FB24763792. verified-results.txt control-content-state.json expanding-content-state.json
0
1
146
1w
Live Activity ending immediately after being created
I'm seeing a Live Activity that's ended almost immediately after I'm creating it. I'm not ending the activity in my code, so something is happening at the system level. iOS version is 18.3.1. Looking at the logs for liveactivitiesd, I see that it was successfully created: default 12:57:34.837266-0800 liveactivitiesd Created activity: 22713DF6-E853-4B34-85FA-CD08D8FCA91B default 12:57:34.837639-0800 liveactivitiesd Starting activity: identifier: 22713DF6-E853-4B34-85FA-CD08D8FCA91B; createdDate: 2025-02-17 20:57:34 +0000; state: active; deviceIdentifier: local; resolvedContentSources: [ActivityKit.ActivityContentSource.process(target: <snip>), ActivityKit.ActivityContentSource.sync]; lastUpdateDate: 2025-02-17 20:57:34 +0000; endingOptions: nil default 12:57:34.858701-0800 liveactivitiesd Activity did start 22713DF6-E853-4B34-85FA-CD08D8FCA91B But then moments later, it's immediately ended: default 12:57:34.933963-0800 liveactivitiesd Ending activity 22713DF6-E853-4B34-85FA-CD08D8FCA91B for XPC participant content source <private> default 12:57:34.933983-0800 liveactivitiesd Stopping activity: 22713DF6-E853-4B34-85FA-CD08D8FCA91B default 12:57:34.934019-0800 liveactivitiesd Activity: identifier: 22713DF6-E853-4B34-85FA-CD08D8FCA91B; createdDate: 2025-02-17 20:57:34 +0000; state: active; deviceIdentifier: local; resolvedContentSources: [ActivityKit.ActivityContentSource.process(target: <snip>), ActivityKit.ActivityContentSource.sync]; lastUpdateDate: 2025-02-17 20:57:34 +0000; endingOptions: nil should be discarded now default 12:57:34.934442-0800 liveactivitiesd Activity discarded: 22713DF6-E853-4B34-85FA-CD08D8FCA91B Again, I'm not ending this activity in my code. I'll occasionally see this happen in my app, and the only solution I've found is to restart my device. Afterwards, everything seems fine. Is this a bug?
4
2
777
1w
AlarmKit leaves an empty zombie Live Activity in Dynamic Island after swipe-dismiss while unlocked
Hi, We are the developers of Morning Call (https://morningcall.info), and we believe we may have identified an AlarmKit / system UI bug on iPhone. We can reproduce the same behavior not only in our app, but also in Apple’s official AlarmKit sample app, which strongly suggests this is a framework or system-level issue rather than an app-specific bug. Demonstration Video of producing zombie Live Activity https://www.youtube.com/watch?v=cZdF3oc8dVI Related Thread https://developer.apple.com/forums/thread/812006 https://developer.apple.com/forums/thread/817305 https://developer.apple.com/forums/thread/807335 Environment iPhone with Dynamic Island Alarm created using AlarmKit Device is unlocked when the alarm begins alerting Steps to reproduce Schedule an AlarmKit alarm. Wait for the alarm to alert while the device is unlocked. The alarm appears in Dynamic Island. Instead of tapping the intended stop or dismiss button, swipe the Dynamic Island presentation away. Expected result The alarm should be fully dismissed. The Live Activity should be removed. No empty UI should remain in Dynamic Island. Actual result The assigned AppIntent runs successfully. Our app code executes as expected. AlarmKit appears to stop the alarm correctly. However, an empty “zombie” Live Activity remains in Dynamic Island indefinitely. The user cannot clear it through normal interaction. Why this is a serious user-facing issue This is not just a cosmetic issue for us. From the user’s perspective, it looks like a Live Activity is permanently stuck in Dynamic Island. More importantly: Force-quitting the app does not remove it Deleting the app does not remove it In practice, many users conclude that our app has left a broken Live Activity running forever We receive repeated user complaints saying that the Live Activity “won’t go away” Because the remaining UI appears to be system-owned, users often do not realize that the only reliable recovery is to restart the phone. Most users do not discover that workaround on their own, so they instead assume the app is severely broken. Cases where the zombie state disappears Rebooting the phone Waiting for the next AlarmKit alert, then pressing the proper stop button on that alert Additional observations Inside our LiveActivityIntent, calling AlarmManager.shared.stop(id:) reports that the alarm has already been stopped by the system. We also tried inspecting Activity<AlarmAttributes<...>>.activities and calling end(..., dismissalPolicy: .immediate), but in this state no matching activity is exposed to the app. This suggests that the alarm itself has already been stopped, but the system-owned Live Activity UI is not being cleaned up correctly after the swipe-dismiss path. Why this does not appear to be an app logic issue The intent is invoked successfully. The alarm stop path is reached. The alarm is already considered stopped by the system. The remaining UI appears to be system-owned. The stuck UI persists even after our own cleanup logic has run. The stuck UI also survives app force-quit and app deletion.
10
13
2.7k
2w
Live Activity Shows Only Black Dynamic Island UI (No Content Rendering) — Widget Extension Receives Updates but SwiftUI UI Is Empty
Hi all, very new "developer" trying to build my own app. The app works, just trying to improve it. I’m implementing a Live Activity in a widget extension (Swift/SwiftUI) for an app built with Flutter as the host app. ActivityKit is functioning correctly—activities start, update, and end normally, and the widget extension receives all state updates. However, the Live Activity UI renders as a completely black capsule (both compact and expanded Dynamic Island, as well as the Lock Screen presentation). The system shows the Live Activity container, but none of the SwiftUI content displays. Verified so far: ActivityAttributes contains at least one stored property (previously empty). ContentState fully Codable + Hashable. All Dynamic Island regions return visible test UI (Text/Image). No .containerBackground() usage. Added explicit .activityBackgroundTint() + system foreground colors. All Swift files included in widget extension target. No runtime errors, no decode failures, no SwiftUI logs. Widget previews work. Clean build, app reinstall, device reboot. Entitlements and Info.plist appear valid. Problem: The widget extension returns a completely black UI on-device, despite valid SwiftUI content in ActivityConfiguration. The Live Activity “shell” renders, so the activity is recognized, but the widget’s view hierarchy is visually empty. Question: Under what conditions would a widget extension produce a black, empty UI for a Live Activity even when ActivityKit, previews, and the SwiftUI layout are correct? Are there known cases where: Widget extension Info.plist misconfiguration, Incorrect background/tint handling, Rendering issues in Dynamic Island, Host app integrations (Flutter), Or extension isolation issues cause valid SwiftUI to fail to render in a Live Activity? Any guidance on deeper debugging steps or known system pitfalls would be appreciated.
4
0
450
Jul ’26
Live activities not updating on lock screen
I'm working on adding Live Activities to my app but I'm running into a problem, and I'm wondering if anyone knows what's going on. The live activities are started and updated entirely via push notifications (sent through FCM). On the lock screen, updates come through fine for a while, but then the activity gets stuck while the phone is locked. The moment I unlock the device, it immediately jumps to the latest state. I've tried different update frequencies and sending with both priority 5 and priority 10, but no luck. I've also looked through the liveactivitiesd logs, but I'm not really sure what I should be looking for. And yes, NSSupportsLiveActivitiesFrequentUpdates is enabled.
1
1
876
Jul ’26
Recommended approach for updating a push-to-start Live Activity when the app is force-quit?
I create a Live Activity remotely via push-to-start, then use its per-activity token (Activity.pushTokenUpdates) so my server can send update/end pushes. To make sure I'm not missing tokens, I observe Activity.activityUpdates and prime from the Activity.activities snapshot at launch and on sceneWillEnterForeground, then subscribe each activity's pushTokenUpdates and POST the token to my server. This works reliably while the app is running or backgrounded/suspended — the system wakes it and I capture the token. The problem is the user force-quit case (swiped from the App Switcher, never reopened): Push-to-start still creates the Live Activity and it renders correctly on the Lock Screen. But pushTokenUpdates never fires, so my server never receives the per-activity token and can't update or end that activity. A backgrounded (not force-quit) app, as a control, captures the token every time. So it seems specific to user-termination rather than all "not running" states. I understand force-quit apps generally aren't granted background runtime — I'm trying to confirm whether that applies here and what the right pattern is. What's the recommended approach? Specifically: Is there any supported way to get the per-activity token to my server while the app stays force-quit — e.g. from the widget extension (does it have any access to Activity.pushToken, or only ActivityViewContext?) or a Notification Service Extension? 2. If not, is setting stale-date on the start push the intended way to let the card expire gracefully when it can never be ended via push? 3. Is there a better pattern for keeping a push-started Live Activity correct when the app is never relaunched?
1
0
1.3k
Jul ’26
Live Activities Push-to-Start flows
Good morning, We are implementing Live Activities in a push-to-start flow. We wrap the listener for push to start tokens in a high priority task: if ptsListenerTask == nil || ptsListenerTask?.isCancelled == true { ptsListenerTask = Task(priority: .high) { [weak self] in for await pushToken in Activity<LiveAuctionAttributes>.pushToStartTokenUpdates { //Send token to back-end } } I've tried a few variations of this and they work well on most devices. I have seen a couple of devices that refuse to issue a push to start token. The user will have logging for the init flow and starting the PTS listener then the logs just go silent, nothing happens. One thing that seemed to work was getting the user to start a Live Activity manually (from our debugging tool) then the PTS token gets issued. This is not very reliable and working a mock live activity into the flow for obtaining a PTS token is a poor solution. Is anyone else seeing this and is there a known issue with obtaining PTS tokens? Thanks! Brad
12
2
1.7k
Jun ’26
TimeDataSource .dateRange(endingAt:) won't update
Hello, I'm trying to add a new Live Activity to my app showing a timer to a specific date and time. I thought I could use some TimeDataSource so that the timer would be updated automatically by SwiftUI without relying on Live Activity updates. That's not the case with .dateRange(endingAt:) though. Text(.dateRange(endingAt: targetDate), format: .components(style: .narrow)) Something like this correctly shows the timer exactly how I want it, but it never updates. Other TimeDataSource like .currentDate and .durationOffset(to:) do update automatically, but are not what I'm looking for. Am I missing something? Should I use another formatter to make it work?
0
0
869
Jun ’26
Live Activity Stops Updating After 30 Seconds in Background During Audio Playback
Hi I developed a music app that plays offline audio and displays lyrics using Live Activities. According to ActivityKit documentation, Live Activities can be updated from the background. However, in my case, updates stop after ~30 seconds when the app goes to the background or the device is locked. Important points: The app continues running in the background (audio playback works fine using AVAudioSession with .playback) Background code execution is working as expected Only the Live Activity stops updating I am not using push updates since this is an offline app. Is there any limitation or requirement for updating Live Activities continuously in the background during audio playback? Audio Session Configuration let session = AVAudioSession.sharedInstance() try session.setCategory( .playback, mode: .default, options: [.mixWithOthers] // ✅ DO NOT interrupt other audio ) try session.setActive(true) print("✅ [AudioSession] Activated with mixWithOthers") } catch { print("❌ [AudioSession] Error: \(error)") } Live Activity Update Methods guard let activity = getLiveActivity(for: recordID) else{ print("⚠️ No Live Activity found for recordID: \(recordID)") return } guard activity.activityState == .active else { print("⚠️ Activity is not active") return } Task { let content = ActivityContent( state: state, staleDate: Date().addingTimeInterval(60 * 60 * 12), relevanceScore: 1.0 ) await activity.update(content) print("✅ Live Activity updated with ActivityContent") } }
1
0
1.8k
Jun ’26
Sample Code with Swift 6
I find these sample projects quite valuable: https://developer.apple.com/documentation/widgetkit/emoji-rangers-supporting-live-activities-interactivity-and-animations https://developer.apple.com/documentation/coredata/sharing-core-data-objects-between-icloud-users . Both use Swift 5, and it is not trivial to adopt Swift 6 with them. Any plans to update them? What is best approach for adopting Swift 6 on such sample code?
5
0
1.5k
Jun ’26
Push to Start Live Activity — dismissal-date not supported in start payload causes un-dismissable notifications
Hey everyone, We're using Push to Start Live Activities in our app (District: Movies Events Dining) where all Live Activities are entirely server-driven. At District, we've taken a unique approach to Live Activities. Since our customers often plan ahead reserving restaurant tables early in the week or booking movies days in advance we needed a way to surface timely, relevant information without requiring the app to be open. We power our Live Activities entirely from the server using Push to Start and Push to Update. This means the Live Activity is initiated and kept up to date by our backend from reservation confirmation all the way to the day of the experience. Whether it's a dining slot or a movie showtime, the Live Activity automatically appears in the notification tray with all relevant details, right when you need it no app launch required. FB Number: FB22062904 Problem: When a Push to Start payload is sent from the server, the user sees an Allow / Don't Allow prompt on their lock screen. If the user ignores this prompt (neither taps Allow nor Don't Allow), the Live Activity card stays stuck in the notification tray permanently with zero way to dismiss it programmatically. This happens because: The activity never officially "starts" on device Activity.end() cannot be called — there's nothing to end Sending an update/end push has no effect dismissal-date is not honoured in the start payload Steps to Reproduce Send a push-to-start APNs payload to a device Do NOT tap Allow or Don't Allow on the prompt Observe — card stays in notification tray indefinitely Send an end push from server — no effect Current Payload { "aps": { "timestamp": 1234567890, "event": "start", "alert": { "title": "Your table is reserved", "body": "Tap to view your reservation" }, "content-state": { ... }, "attributes-type": "ReservationActivityAttributes", "attributes": { ... } // ❌ dismissal-date has no effect here } } Expected Behaviour dismissal-date should be honoured in the push-to-start payload, so that if the user ignores the prompt, the notification auto-dismisses after the specified time — consistent with how standard Live Activity expiry works. Suggested Fix { "aps": { "timestamp": 1234567890, "event": "start", "content-state": { ... }, "dismissal-date": 1234568490 // ✅ honour this } } Impact This affects any app using server-driven Live Activities — dining reservations, movie bookings, food delivery, ride hailing, ticketing etc. Without this, there is no way to prevent permanent notification tray pollution for users who ignore the Allow prompt. Has anyone found a workaround for this? Would love to know if others are hitting the same issue.
0
3
794
Jun ’26
Live Activity reports .active via ActivityKit but widget extension never renders or appears in process list (works fine in isolated test project)
I'm seeing a Live Activity that successfully starts via Activity.request() — activityState returns .active, a valid ActivityKit push token is issued and works correctly — but nothing ever appears on the Lock Screen, and the widget extension process never shows up in Xcode's Debug → Attach to Process list (the main app process does appear). This happens consistently across many clean rebuilds. Setup: Flutter app (using the live_activities Flutter plugin, which wraps ActivityKit) with a native iOS Widget Extension target for the Live Activity Xcode 26.5, iOS 18.7.9 on a physical iPhone XS Max Bundle ID: com.santitech.foodboda, extension: com.santitech.foodboda.FoodbodaLiveActivity NSSupportsLiveActivities = YES confirmed in both the main app's Info.plist and the extension's Info.plist (verified in the compiled .appex binary itself, not just source) App Group entitlement confirmed present in both compiled provisioning profiles via security cms -D on embedded.mobileprovision Deployment target 16.6 on both targets (Live Activities require 16.1+) Settings → [App] → Live Activities toggle confirmed ON; Low Power Mode OFF What I've already ruled out: Target membership of Swift source files — confirmed correct in File Inspector WidgetBundle only references the real Live Activity widget (removed unused Control/home-widget/AppIntent boilerplate) Info.plist NSExtensionPointIdentifier = com.apple.widgetkit-extension — correct Built a brand-new, separate, minimal test app+extension from Xcode's default template, using the exact same Attributes/ContentState/SwiftUI view code as the main app (copy-pasted verbatim) — this minimal test successfully renders on the Lock Screen on the same physical device. This proves the Swift code itself, the device, and the Apple ID/provisioning are all capable of supporting Live Activities correctly. Confirmed areActivitiesEnabled() returns true and getActivityState() returns .active on every test Tested with full app delete + device restart + DerivedData wipe between attempts — no change Question: Given that identical code works in an isolated minimal project but not in the main app's bundle ID, what could cause this specific symptom — ActivityKit registering an activity as active while WidgetKit never instantiates the extension to render it — tied to one specific app/bundle identifier rather than the device or account in general? Is there a known interaction with App Groups that have been reconfigured many times during development, or any way to fully reset WidgetKit's registration state for a specific bundle ID short of changing the bundle identifier entirely?
0
0
841
Jun ’26
Activity.pushToStartToken is nil and pushToStartTokenUpdates never emits, even after delayed retry
I am using ActivityKit push-to-start Live Activities on iOS 17.2 and later. In a small number of user reports, the app is never able to obtain Activity<LiveActivityAttributes>.pushToStartToken. The flow is: Task { if let token = Activity<LiveActivityAttributes>.pushToStartToken { // cache and upload token } else { // logged: current push-to-start token is nil } for await token in Activity<LiveActivityAttributes>.pushToStartTokenUpdates { // cache and upload token } } This task is started when the app launches. For the affected users: Activity<LiveActivityAttributes>.pushToStartToken returns nil at app launch. Activity<LiveActivityAttributes>.pushToStartTokenUpdates never emits any value. After waiting for a while, reading Activity<LiveActivityAttributes>.pushToStartToken again still returns nil. When an existing Live Activity ends or expires, the app retries and reads Activity<LiveActivityAttributes>.pushToStartToken again, but it is still nil. Example log from the retry after the Live Activity ended: [Live Activity][retryDisplayCreationAfterLiveActivityEnded] Failed to read PushToStart token. local entity is nil: true In this case, the local entity is empty because no push-to-start token was ever received from ActivityKit. This is not about the per-activity activity.pushToken; the issue is specifically with the app-level Activity<Attributes>.pushToStartToken. Because the push-to-start token remains empty, our server cannot send a push-to-start request for that user. I have seen a previous forum response mentioning a timing issue before iOS 26, but this affected case is on iOS 26.5, so I am not sure whether this is the same issue or a different condition. Questions: Under what conditions can Activity<Attributes>.pushToStartToken remain nil indefinitely? Is pushToStartTokenUpdates expected to emit the current token after app launch, or only future token changes? If the initial pushToStartToken read returns nil, what is the recommended retry strategy on iOS 26.5? Does Live Activities authorization, notification permission, APNs registration state, app install source, or device state affect generation of the push-to-start token? What logs or sysdiagnose information would be useful to confirm whether this is an ActivityKit issue? Environment: iOS version: 26.5 Device model: iPhone 17 App install source: TestFlight Xcode version: 26.3 ActivityKit usage: push-to-start Live Activity Any guidance on whether this is expected behavior, a known issue, or something we should file through Feedback Assistant would be appreciated.
1
0
814
Jun ’26
Live Activity without Dynamic Island
Hi team, I’m working on an ActivityKit use case where a Live Activity is useful on the Lock Screen, but not in the Dynamic Island. Today, Live Activities appear to be treated as a unified presentation across system surfaces: Lock Screen, Dynamic Island, StandBy, etc. For our app, the Lock Screen presentation is the right user experience, but showing the same activity in the Dynamic Island creates unnecessary persistent foreground UI while the user is actively using the device. Is there any supported way to create a Live Activity that appears on the Lock Screen but opts out of Dynamic Island presentation on supported iPhones? If not, I’d love to request an ActivityKit enhancement that lets developers specify supported presentation destinations for a Live Activity, for example something like: Lock Screen only or Lock Screen + StandBy, but not Dynamic Island This would be useful for apps where the Live Activity is meant to act as a passive lock-screen status/reminder, rather than an ongoing foreground indicator. Thanks!
0
0
943
Jun ’26
Live Activities: no minute-granularity self-updating countdown text; custom DiscreteFormatStyle types fail to decode in the system renderer
Summary There is no supported way for a Live Activity to display a self-updating countdown at minute granularity in the form transit riders expect — a bare "7 min" that ticks to "6 min" — even though Apple's own apps (Timer in the Dynamic Island, Maps ETA) display exactly this form. The API that should make this possible — Text(_ input: TimeDataSource<Date>, format:) with a custom DiscreteFormatStyle (added in iOS 18) — compiles and archives, but the rendered activity fails at decode time in the system renderer, so every region of the Live Activity displays grey placeholder boxes. What I'm building An NYC subway departures app. The app's design language everywhere (in-app, home screen widgets via baked timeline entries) is "7 min" / "Now". Real-world fidelity is minute-level: riders don't think in mm:ss. The Live Activity is the only surface that cannot match this design, because it can only use self-updating text between content updates, and none of the built-in live formats produce it. Built-in options and why each falls short Text(timerInterval:countsDown:) — mm:ss only; no minute-granularity mode (this is FB23091094). Also reserves maximum width (FB23091111). Text(date, style: .relative) — always appends a second unit ("7 min, 30 sec") and counts up ambiguously (unsigned) after the date passes. .reference(to:allowedFields:maxFieldCount:) (iOS 18) — closest usable option, but only spelled-out wide units with a mandatory preposition: "in 7 minutes". No abbreviated/narrow width option exists on SystemFormatStyle.DateReference. .offset(to:) (iOS 18) — measures time since the anchor, so an upcoming departure renders as a negative value ("−7 minutes"); inverted for countdown use, and also wide-units only. The bug: custom DiscreteFormatStyle fails to decode in the renderer A custom format style solves this completely — mine rendered exact "7 min"/"Now" strings and, by holding the full departure list, even advanced to the next train the moment one departed, all without waking the app: @available(iOS 18.0, *) struct TrainCountdownFormat: DiscreteFormatStyle { var departures: [Date] var rank: Int // 0 = closest upcoming train var fullText: Bool // "7 min" vs "7m" func format(_ now: Date) -> String { let upcoming = departures.filter { $0 > now }.sorted() guard rank < upcoming.count else { return "—" } let totalSeconds = Int(upcoming[rank].timeIntervalSince(now)) if totalSeconds < 60 { return "Now" } let minutes = totalSeconds / 60 return fullText ? "\(minutes) min" : "\(minutes)m" } func discreteInput(after input: Date) -> Date? { departures.compactMap { departure -> Date? in let seconds = departure.timeIntervalSince(input) guard seconds > 0 else { return nil } let intoMinute = seconds.truncatingRemainder(dividingBy: 60) return input.addingTimeInterval(intoMinute > 0 ? intoMinute : 60) }.min() } func discreteInput(before input: Date) -> Date? { departures.compactMap { departure -> Date? in let seconds = departure.timeIntervalSince(input) guard seconds > 0 else { return departure < input ? departure : departure.addingTimeInterval(-60) } let intoMinute = seconds.truncatingRemainder(dividingBy: 60) return input.addingTimeInterval(intoMinute - 60) }.max() } } // In the ActivityConfiguration views: Text(.currentDate, format: TrainCountdownFormat(departures: dates, rank: 0, fullText: true)) This compiles and the activity is created, but every presentation (compact trailing, expanded, lock screen) renders as grey placeholder boxes. The console shows the archive being rejected at decode time in the renderer process: WidgetRenderer_Activities: (WidgetRenderer) [com.apple.chrono:activityRendererClient-verbose] Failed to return view entry from archive for view model with tag dynamicIsland-compactTrailing with error: SwiftUI.AnyCodable<...SafelyCodableRequirement>...Errors.noType(mangledName: "7SwiftUI18TimeDataFormattingO10ResolvableVy_AA0cD6SourceVAAE11DateStorageOy10Foundation0H0V_G 27NowDepartingWidgetExtension10$1030be9a0yXZ20TrainCountdownFormatV G") i.e. the archived TimeDataFormatting.Resolvable wrapper references a type defined in the app's widget extension, which the system renderer cannot look up. Nothing in the DiscreteFormatStyle or Text(_:format:) documentation states that only system-defined format styles are renderable in Live Activities, and there is no compile-time or runtime diagnostic surfaced to the developer — the activity just renders blank. Requests (either would unblock this) Support custom DiscreteFormatStyle types in Live Activity rendering (e.g. by evaluating the format in the extension's process when pre-rendering discrete frames), or at minimum document the limitation and fail loudly instead of rendering placeholder boxes. Add minute-granularity and unit-width options to the built-in live formats: a showsSeconds/fields option on Text(timerInterval:) (FB23091094), and/or a units-width option (abbreviated/narrow) plus a "bare duration, no preposition, countdown sign convention" variant on SystemFormatStyle.DateReference / DateOffset. Steps to reproduce Create a Live Activity whose views use Text(.currentDate, format:) with any custom DiscreteFormatStyle (sample above). Start the activity; background the app. Observe the Dynamic Island and lock screen render grey placeholder boxes for every region, and WidgetRenderer_Activities logs Errors.noType for each view model tag. Expected: the custom format renders and updates at the boundaries reported by discreteInput(before:/after:), as it does for the system styles. Actual: decode failure in the renderer; entire activity renders as placeholders. Environment Xcode 27.0 (27A266a) iOS 27.0 simulator, iPhone 18 Pro (also applies to iOS 18+ per API availability) Widget extension deployment target: iOS 17.6 Related reports: FB23091094, FB23091111, forum thread https://developer.apple.com/forums/thread/834337
Replies
0
Boosts
0
Views
17
Activity
8h
Inconsistencies with activityBackgroundTint when a device switches between light and dark modes
While the activityBackgroundTint modifier is intended to set the background color of a Live Activity, it often fails to dynamically update, leaving the activity with an incorrect background. Replacing it with ZStack { Color(.background) .... } solves the problem, but this is a workaround. The activityBackgroundTint modifier is still needed, at a minimum, so that the "Allow Live Activity for the app" extension does not have the default color.
Topic: Design SubTopic: General Tags:
Replies
3
Boosts
1
Views
601
Activity
8h
Screen capture of other apps without the broadcast picker — any public API?
Two quick questions about ReplayKit on iOS: Is there any public API or entitlement that lets an app capture the screen while another app is in the foreground without presenting RPSystemBroadcastPickerView each session? Is custom-content Picture-in-Picture (AVSampleBufferDisplayLayer with AVPictureInPictureController) considered acceptable for a non-video status overlay, or is Live Activities the intended surface for that? Thanks.
Replies
0
Boosts
0
Views
262
Activity
4d
AlarmKit alarms fire late (or not until you wake up the iPhone)
Hey all, I've submitted a couple Feedback reports on this (FB22887867 on iOS 26 and FB24483266 on iOS 27), but wanted to share here for 1. validation that I'm not the only one experiencing this issue and 2. ask for ideas or experience with potential workarounds. The issue is that AlarmKit alarms, even when properly configured and scheduled from an app, will intermittently fire late, or not fire at all until the iPhone is woken up. For example, you might create an AlarmKit alarm with a relative schedule for 6:00am, then lock your iPhone before bed. When 6:00am passes, nothing happens. Then, at 6:13am it fires (with the full screen alert, audio and haptics) Or, you might wake up at 6:53am, notice that it didn't fire, tap the screen on your iPhone, the Lock Screen displays for about a second, then all of a sudden, the AlarmKit alert presents (with the full screen alert, audio and haptics). The issue has been present from iOS 26.0 up through the iOS 27.0 RC. I'm fairly confident that this is not a configuration issue. I've reproduced it using the WWDC 25 AlarmKit sample code and if you read from AlarmManager.shared.alarms, these alarms show up as expected: with a scheduled state and the correct times. The issue seems to be more common overnight, when the iPhone has been asleep for a while. It's less common on my personal iPhone but occurs probably once out of every 3 to 5 alarms on my test iPhones (which have much less interaction and background activity etc.). Of our app's few thousand daily users, we get complaints at least once a day. I've dropped a few sysdiagnose reports into Claude. In every instance, it claims that when the alarm was scheduled, mobiletimerd successfully registered an XPC wake-up for the alarm. However, during a completely unrelated event overnight (ex: a wifi packet), launchd drops the scheduled wake-up and nothing re-schedules it. So when 6:00am rolls around, nothing wakes up the iPhone to let the alarm fire. On days when it fires late, it's simply because another unrelated event (ex: a wifi packet) woke up the iPhone while the late alarm was queued. Looking forward to hearing your thoughts. Thank you.
Replies
1
Boosts
0
Views
119
Activity
5d
ActivityKit: sub-4KB JSON content-state exceeds size limit after numeric reserialization
I've filed FB24763792 about numeric JSON reserialization and the Live Activity content-state size limit. A compact JSON content-state can be below 4,096 bytes but expand beyond that limit when Foundation parses and reserializes its numbers. Here is an entirely synthetic Foundation reproduction: import Foundation let row = #"{"a":1.91,"b":1.91}"# let rows = Array(repeating: row, count: 100).joined(separator: ",") let input = Data("{"sequence":1,"readings":[(rows)]}".utf8) let object = try JSONSerialization.jsonObject(with: input) let output = try JSONSerialization.data(withJSONObject: object, options: []) print(input.count, output.count) On macOS 26.6.2 and the iOS 26.5 simulator, this prints 2027 4827. Foundation writes 1.91 as 1.9099999999999999. Change both values to 1.95 and it prints 2027 2027. In a separate local ActivityKit test, we passed the Foundation-reserialized data through a Decimal-based Codable state that preserved the expanded byte count: The 1.95 control remained at 2,027 bytes and applied successfully. The 1.91 case expanded to 4,827 bytes and was rejected with "Payload maximum size exceeded." The activity retained its previous state. We also tested the exact boundary: a 4,096-byte encoded dynamic state applied, while 4,097 bytes was rejected. Static attributes did not count toward that tested local-update boundary. This investigation began with remote Live Activities remaining stale while APNs returned HTTP 200 for dispatched updates. The device logged "Error extracing payload from incoming message" (spelling as logged). We are confident numeric expansion is the mechanism behind our issue. The tests above reproduce expansion and rejection locally; they do not replay an exact captured failed remote push. The ContentState documentation specifies a 4KB limit but doesn't make remote JSON normalization clear: https://developer.apple.com/documentation/activitykit/activityattributes/contentstate Questions for Apple: At what stage is remote content-state size measured? Can internal reserialization preserve compact numeric representations, or can the limit use the supplied content-state bytes? Can rejected incoming updates expose the underlying size error and measured byte count? The synthetic reproducer and a simulator diagnostic collected immediately after the local rejection are attached to FB24763792. verified-results.txt control-content-state.json expanding-content-state.json
Replies
0
Boosts
1
Views
146
Activity
1w
Changes to Activity/WidgetKit LiveActivities in iOS 27
Hi, for anyone who is working with LiveActivities and is running a beta of iOS 27, has apple made the ability for LiveActivities to be vertically larger and display more content as they appear in some of the demo images, or are these LiveActivities like the ones in the pictures above just system specific that is only available to apple.
Replies
0
Boosts
0
Views
238
Activity
1w
Live Activity ending immediately after being created
I'm seeing a Live Activity that's ended almost immediately after I'm creating it. I'm not ending the activity in my code, so something is happening at the system level. iOS version is 18.3.1. Looking at the logs for liveactivitiesd, I see that it was successfully created: default 12:57:34.837266-0800 liveactivitiesd Created activity: 22713DF6-E853-4B34-85FA-CD08D8FCA91B default 12:57:34.837639-0800 liveactivitiesd Starting activity: identifier: 22713DF6-E853-4B34-85FA-CD08D8FCA91B; createdDate: 2025-02-17 20:57:34 +0000; state: active; deviceIdentifier: local; resolvedContentSources: [ActivityKit.ActivityContentSource.process(target: <snip>), ActivityKit.ActivityContentSource.sync]; lastUpdateDate: 2025-02-17 20:57:34 +0000; endingOptions: nil default 12:57:34.858701-0800 liveactivitiesd Activity did start 22713DF6-E853-4B34-85FA-CD08D8FCA91B But then moments later, it's immediately ended: default 12:57:34.933963-0800 liveactivitiesd Ending activity 22713DF6-E853-4B34-85FA-CD08D8FCA91B for XPC participant content source <private> default 12:57:34.933983-0800 liveactivitiesd Stopping activity: 22713DF6-E853-4B34-85FA-CD08D8FCA91B default 12:57:34.934019-0800 liveactivitiesd Activity: identifier: 22713DF6-E853-4B34-85FA-CD08D8FCA91B; createdDate: 2025-02-17 20:57:34 +0000; state: active; deviceIdentifier: local; resolvedContentSources: [ActivityKit.ActivityContentSource.process(target: <snip>), ActivityKit.ActivityContentSource.sync]; lastUpdateDate: 2025-02-17 20:57:34 +0000; endingOptions: nil should be discarded now default 12:57:34.934442-0800 liveactivitiesd Activity discarded: 22713DF6-E853-4B34-85FA-CD08D8FCA91B Again, I'm not ending this activity in my code. I'll occasionally see this happen in my app, and the only solution I've found is to restart my device. Afterwards, everything seems fine. Is this a bug?
Replies
4
Boosts
2
Views
777
Activity
1w
AlarmKit leaves an empty zombie Live Activity in Dynamic Island after swipe-dismiss while unlocked
Hi, We are the developers of Morning Call (https://morningcall.info), and we believe we may have identified an AlarmKit / system UI bug on iPhone. We can reproduce the same behavior not only in our app, but also in Apple’s official AlarmKit sample app, which strongly suggests this is a framework or system-level issue rather than an app-specific bug. Demonstration Video of producing zombie Live Activity https://www.youtube.com/watch?v=cZdF3oc8dVI Related Thread https://developer.apple.com/forums/thread/812006 https://developer.apple.com/forums/thread/817305 https://developer.apple.com/forums/thread/807335 Environment iPhone with Dynamic Island Alarm created using AlarmKit Device is unlocked when the alarm begins alerting Steps to reproduce Schedule an AlarmKit alarm. Wait for the alarm to alert while the device is unlocked. The alarm appears in Dynamic Island. Instead of tapping the intended stop or dismiss button, swipe the Dynamic Island presentation away. Expected result The alarm should be fully dismissed. The Live Activity should be removed. No empty UI should remain in Dynamic Island. Actual result The assigned AppIntent runs successfully. Our app code executes as expected. AlarmKit appears to stop the alarm correctly. However, an empty “zombie” Live Activity remains in Dynamic Island indefinitely. The user cannot clear it through normal interaction. Why this is a serious user-facing issue This is not just a cosmetic issue for us. From the user’s perspective, it looks like a Live Activity is permanently stuck in Dynamic Island. More importantly: Force-quitting the app does not remove it Deleting the app does not remove it In practice, many users conclude that our app has left a broken Live Activity running forever We receive repeated user complaints saying that the Live Activity “won’t go away” Because the remaining UI appears to be system-owned, users often do not realize that the only reliable recovery is to restart the phone. Most users do not discover that workaround on their own, so they instead assume the app is severely broken. Cases where the zombie state disappears Rebooting the phone Waiting for the next AlarmKit alert, then pressing the proper stop button on that alert Additional observations Inside our LiveActivityIntent, calling AlarmManager.shared.stop(id:) reports that the alarm has already been stopped by the system. We also tried inspecting Activity<AlarmAttributes<...>>.activities and calling end(..., dismissalPolicy: .immediate), but in this state no matching activity is exposed to the app. This suggests that the alarm itself has already been stopped, but the system-owned Live Activity UI is not being cleaned up correctly after the swipe-dismiss path. Why this does not appear to be an app logic issue The intent is invoked successfully. The alarm stop path is reached. The alarm is already considered stopped by the system. The remaining UI appears to be system-owned. The stuck UI persists even after our own cleanup logic has run. The stuck UI also survives app force-quit and app deletion.
Replies
10
Boosts
13
Views
2.7k
Activity
2w
Some users doesn't get live activities
Some users are reporting that they don't see Live Activities, but our logs show that the trigger was sent successfully. Is there a way to investigate on the client side why the Live Activity didn't appear? Logs on client side? anything?
Replies
1
Boosts
0
Views
906
Activity
Jul ’26
Live Activity Shows Only Black Dynamic Island UI (No Content Rendering) — Widget Extension Receives Updates but SwiftUI UI Is Empty
Hi all, very new "developer" trying to build my own app. The app works, just trying to improve it. I’m implementing a Live Activity in a widget extension (Swift/SwiftUI) for an app built with Flutter as the host app. ActivityKit is functioning correctly—activities start, update, and end normally, and the widget extension receives all state updates. However, the Live Activity UI renders as a completely black capsule (both compact and expanded Dynamic Island, as well as the Lock Screen presentation). The system shows the Live Activity container, but none of the SwiftUI content displays. Verified so far: ActivityAttributes contains at least one stored property (previously empty). ContentState fully Codable + Hashable. All Dynamic Island regions return visible test UI (Text/Image). No .containerBackground() usage. Added explicit .activityBackgroundTint() + system foreground colors. All Swift files included in widget extension target. No runtime errors, no decode failures, no SwiftUI logs. Widget previews work. Clean build, app reinstall, device reboot. Entitlements and Info.plist appear valid. Problem: The widget extension returns a completely black UI on-device, despite valid SwiftUI content in ActivityConfiguration. The Live Activity “shell” renders, so the activity is recognized, but the widget’s view hierarchy is visually empty. Question: Under what conditions would a widget extension produce a black, empty UI for a Live Activity even when ActivityKit, previews, and the SwiftUI layout are correct? Are there known cases where: Widget extension Info.plist misconfiguration, Incorrect background/tint handling, Rendering issues in Dynamic Island, Host app integrations (Flutter), Or extension isolation issues cause valid SwiftUI to fail to render in a Live Activity? Any guidance on deeper debugging steps or known system pitfalls would be appreciated.
Replies
4
Boosts
0
Views
450
Activity
Jul ’26
Live activities not updating on lock screen
I'm working on adding Live Activities to my app but I'm running into a problem, and I'm wondering if anyone knows what's going on. The live activities are started and updated entirely via push notifications (sent through FCM). On the lock screen, updates come through fine for a while, but then the activity gets stuck while the phone is locked. The moment I unlock the device, it immediately jumps to the latest state. I've tried different update frequencies and sending with both priority 5 and priority 10, but no luck. I've also looked through the liveactivitiesd logs, but I'm not really sure what I should be looking for. And yes, NSSupportsLiveActivitiesFrequentUpdates is enabled.
Replies
1
Boosts
1
Views
876
Activity
Jul ’26
Recommended approach for updating a push-to-start Live Activity when the app is force-quit?
I create a Live Activity remotely via push-to-start, then use its per-activity token (Activity.pushTokenUpdates) so my server can send update/end pushes. To make sure I'm not missing tokens, I observe Activity.activityUpdates and prime from the Activity.activities snapshot at launch and on sceneWillEnterForeground, then subscribe each activity's pushTokenUpdates and POST the token to my server. This works reliably while the app is running or backgrounded/suspended — the system wakes it and I capture the token. The problem is the user force-quit case (swiped from the App Switcher, never reopened): Push-to-start still creates the Live Activity and it renders correctly on the Lock Screen. But pushTokenUpdates never fires, so my server never receives the per-activity token and can't update or end that activity. A backgrounded (not force-quit) app, as a control, captures the token every time. So it seems specific to user-termination rather than all "not running" states. I understand force-quit apps generally aren't granted background runtime — I'm trying to confirm whether that applies here and what the right pattern is. What's the recommended approach? Specifically: Is there any supported way to get the per-activity token to my server while the app stays force-quit — e.g. from the widget extension (does it have any access to Activity.pushToken, or only ActivityViewContext?) or a Notification Service Extension? 2. If not, is setting stale-date on the start push the intended way to let the card expire gracefully when it can never be ended via push? 3. Is there a better pattern for keeping a push-started Live Activity correct when the app is never relaunched?
Replies
1
Boosts
0
Views
1.3k
Activity
Jul ’26
Live Activities Push-to-Start flows
Good morning, We are implementing Live Activities in a push-to-start flow. We wrap the listener for push to start tokens in a high priority task: if ptsListenerTask == nil || ptsListenerTask?.isCancelled == true { ptsListenerTask = Task(priority: .high) { [weak self] in for await pushToken in Activity<LiveAuctionAttributes>.pushToStartTokenUpdates { //Send token to back-end } } I've tried a few variations of this and they work well on most devices. I have seen a couple of devices that refuse to issue a push to start token. The user will have logging for the init flow and starting the PTS listener then the logs just go silent, nothing happens. One thing that seemed to work was getting the user to start a Live Activity manually (from our debugging tool) then the PTS token gets issued. This is not very reliable and working a mock live activity into the flow for obtaining a PTS token is a poor solution. Is anyone else seeing this and is there a known issue with obtaining PTS tokens? Thanks! Brad
Replies
12
Boosts
2
Views
1.7k
Activity
Jun ’26
TimeDataSource .dateRange(endingAt:) won't update
Hello, I'm trying to add a new Live Activity to my app showing a timer to a specific date and time. I thought I could use some TimeDataSource so that the timer would be updated automatically by SwiftUI without relying on Live Activity updates. That's not the case with .dateRange(endingAt:) though. Text(.dateRange(endingAt: targetDate), format: .components(style: .narrow)) Something like this correctly shows the timer exactly how I want it, but it never updates. Other TimeDataSource like .currentDate and .durationOffset(to:) do update automatically, but are not what I'm looking for. Am I missing something? Should I use another formatter to make it work?
Replies
0
Boosts
0
Views
869
Activity
Jun ’26
Live Activity Stops Updating After 30 Seconds in Background During Audio Playback
Hi I developed a music app that plays offline audio and displays lyrics using Live Activities. According to ActivityKit documentation, Live Activities can be updated from the background. However, in my case, updates stop after ~30 seconds when the app goes to the background or the device is locked. Important points: The app continues running in the background (audio playback works fine using AVAudioSession with .playback) Background code execution is working as expected Only the Live Activity stops updating I am not using push updates since this is an offline app. Is there any limitation or requirement for updating Live Activities continuously in the background during audio playback? Audio Session Configuration let session = AVAudioSession.sharedInstance() try session.setCategory( .playback, mode: .default, options: [.mixWithOthers] // ✅ DO NOT interrupt other audio ) try session.setActive(true) print("✅ [AudioSession] Activated with mixWithOthers") } catch { print("❌ [AudioSession] Error: \(error)") } Live Activity Update Methods guard let activity = getLiveActivity(for: recordID) else{ print("⚠️ No Live Activity found for recordID: \(recordID)") return } guard activity.activityState == .active else { print("⚠️ Activity is not active") return } Task { let content = ActivityContent( state: state, staleDate: Date().addingTimeInterval(60 * 60 * 12), relevanceScore: 1.0 ) await activity.update(content) print("✅ Live Activity updated with ActivityContent") } }
Replies
1
Boosts
0
Views
1.8k
Activity
Jun ’26
Sample Code with Swift 6
I find these sample projects quite valuable: https://developer.apple.com/documentation/widgetkit/emoji-rangers-supporting-live-activities-interactivity-and-animations https://developer.apple.com/documentation/coredata/sharing-core-data-objects-between-icloud-users . Both use Swift 5, and it is not trivial to adopt Swift 6 with them. Any plans to update them? What is best approach for adopting Swift 6 on such sample code?
Replies
5
Boosts
0
Views
1.5k
Activity
Jun ’26
Push to Start Live Activity — dismissal-date not supported in start payload causes un-dismissable notifications
Hey everyone, We're using Push to Start Live Activities in our app (District: Movies Events Dining) where all Live Activities are entirely server-driven. At District, we've taken a unique approach to Live Activities. Since our customers often plan ahead reserving restaurant tables early in the week or booking movies days in advance we needed a way to surface timely, relevant information without requiring the app to be open. We power our Live Activities entirely from the server using Push to Start and Push to Update. This means the Live Activity is initiated and kept up to date by our backend from reservation confirmation all the way to the day of the experience. Whether it's a dining slot or a movie showtime, the Live Activity automatically appears in the notification tray with all relevant details, right when you need it no app launch required. FB Number: FB22062904 Problem: When a Push to Start payload is sent from the server, the user sees an Allow / Don't Allow prompt on their lock screen. If the user ignores this prompt (neither taps Allow nor Don't Allow), the Live Activity card stays stuck in the notification tray permanently with zero way to dismiss it programmatically. This happens because: The activity never officially "starts" on device Activity.end() cannot be called — there's nothing to end Sending an update/end push has no effect dismissal-date is not honoured in the start payload Steps to Reproduce Send a push-to-start APNs payload to a device Do NOT tap Allow or Don't Allow on the prompt Observe — card stays in notification tray indefinitely Send an end push from server — no effect Current Payload { "aps": { "timestamp": 1234567890, "event": "start", "alert": { "title": "Your table is reserved", "body": "Tap to view your reservation" }, "content-state": { ... }, "attributes-type": "ReservationActivityAttributes", "attributes": { ... } // ❌ dismissal-date has no effect here } } Expected Behaviour dismissal-date should be honoured in the push-to-start payload, so that if the user ignores the prompt, the notification auto-dismisses after the specified time — consistent with how standard Live Activity expiry works. Suggested Fix { "aps": { "timestamp": 1234567890, "event": "start", "content-state": { ... }, "dismissal-date": 1234568490 // ✅ honour this } } Impact This affects any app using server-driven Live Activities — dining reservations, movie bookings, food delivery, ride hailing, ticketing etc. Without this, there is no way to prevent permanent notification tray pollution for users who ignore the Allow prompt. Has anyone found a workaround for this? Would love to know if others are hitting the same issue.
Replies
0
Boosts
3
Views
794
Activity
Jun ’26
Live Activity reports .active via ActivityKit but widget extension never renders or appears in process list (works fine in isolated test project)
I'm seeing a Live Activity that successfully starts via Activity.request() — activityState returns .active, a valid ActivityKit push token is issued and works correctly — but nothing ever appears on the Lock Screen, and the widget extension process never shows up in Xcode's Debug → Attach to Process list (the main app process does appear). This happens consistently across many clean rebuilds. Setup: Flutter app (using the live_activities Flutter plugin, which wraps ActivityKit) with a native iOS Widget Extension target for the Live Activity Xcode 26.5, iOS 18.7.9 on a physical iPhone XS Max Bundle ID: com.santitech.foodboda, extension: com.santitech.foodboda.FoodbodaLiveActivity NSSupportsLiveActivities = YES confirmed in both the main app's Info.plist and the extension's Info.plist (verified in the compiled .appex binary itself, not just source) App Group entitlement confirmed present in both compiled provisioning profiles via security cms -D on embedded.mobileprovision Deployment target 16.6 on both targets (Live Activities require 16.1+) Settings → [App] → Live Activities toggle confirmed ON; Low Power Mode OFF What I've already ruled out: Target membership of Swift source files — confirmed correct in File Inspector WidgetBundle only references the real Live Activity widget (removed unused Control/home-widget/AppIntent boilerplate) Info.plist NSExtensionPointIdentifier = com.apple.widgetkit-extension — correct Built a brand-new, separate, minimal test app+extension from Xcode's default template, using the exact same Attributes/ContentState/SwiftUI view code as the main app (copy-pasted verbatim) — this minimal test successfully renders on the Lock Screen on the same physical device. This proves the Swift code itself, the device, and the Apple ID/provisioning are all capable of supporting Live Activities correctly. Confirmed areActivitiesEnabled() returns true and getActivityState() returns .active on every test Tested with full app delete + device restart + DerivedData wipe between attempts — no change Question: Given that identical code works in an isolated minimal project but not in the main app's bundle ID, what could cause this specific symptom — ActivityKit registering an activity as active while WidgetKit never instantiates the extension to render it — tied to one specific app/bundle identifier rather than the device or account in general? Is there a known interaction with App Groups that have been reconfigured many times during development, or any way to fully reset WidgetKit's registration state for a specific bundle ID short of changing the bundle identifier entirely?
Replies
0
Boosts
0
Views
841
Activity
Jun ’26
Activity.pushToStartToken is nil and pushToStartTokenUpdates never emits, even after delayed retry
I am using ActivityKit push-to-start Live Activities on iOS 17.2 and later. In a small number of user reports, the app is never able to obtain Activity<LiveActivityAttributes>.pushToStartToken. The flow is: Task { if let token = Activity<LiveActivityAttributes>.pushToStartToken { // cache and upload token } else { // logged: current push-to-start token is nil } for await token in Activity<LiveActivityAttributes>.pushToStartTokenUpdates { // cache and upload token } } This task is started when the app launches. For the affected users: Activity<LiveActivityAttributes>.pushToStartToken returns nil at app launch. Activity<LiveActivityAttributes>.pushToStartTokenUpdates never emits any value. After waiting for a while, reading Activity<LiveActivityAttributes>.pushToStartToken again still returns nil. When an existing Live Activity ends or expires, the app retries and reads Activity<LiveActivityAttributes>.pushToStartToken again, but it is still nil. Example log from the retry after the Live Activity ended: [Live Activity][retryDisplayCreationAfterLiveActivityEnded] Failed to read PushToStart token. local entity is nil: true In this case, the local entity is empty because no push-to-start token was ever received from ActivityKit. This is not about the per-activity activity.pushToken; the issue is specifically with the app-level Activity<Attributes>.pushToStartToken. Because the push-to-start token remains empty, our server cannot send a push-to-start request for that user. I have seen a previous forum response mentioning a timing issue before iOS 26, but this affected case is on iOS 26.5, so I am not sure whether this is the same issue or a different condition. Questions: Under what conditions can Activity<Attributes>.pushToStartToken remain nil indefinitely? Is pushToStartTokenUpdates expected to emit the current token after app launch, or only future token changes? If the initial pushToStartToken read returns nil, what is the recommended retry strategy on iOS 26.5? Does Live Activities authorization, notification permission, APNs registration state, app install source, or device state affect generation of the push-to-start token? What logs or sysdiagnose information would be useful to confirm whether this is an ActivityKit issue? Environment: iOS version: 26.5 Device model: iPhone 17 App install source: TestFlight Xcode version: 26.3 ActivityKit usage: push-to-start Live Activity Any guidance on whether this is expected behavior, a known issue, or something we should file through Feedback Assistant would be appreciated.
Replies
1
Boosts
0
Views
814
Activity
Jun ’26
Live Activity without Dynamic Island
Hi team, I’m working on an ActivityKit use case where a Live Activity is useful on the Lock Screen, but not in the Dynamic Island. Today, Live Activities appear to be treated as a unified presentation across system surfaces: Lock Screen, Dynamic Island, StandBy, etc. For our app, the Lock Screen presentation is the right user experience, but showing the same activity in the Dynamic Island creates unnecessary persistent foreground UI while the user is actively using the device. Is there any supported way to create a Live Activity that appears on the Lock Screen but opts out of Dynamic Island presentation on supported iPhones? If not, I’d love to request an ActivityKit enhancement that lets developers specify supported presentation destinations for a Live Activity, for example something like: Lock Screen only or Lock Screen + StandBy, but not Dynamic Island This would be useful for apps where the Live Activity is meant to act as a passive lock-screen status/reminder, rather than an ongoing foreground indicator. Thanks!
Replies
0
Boosts
0
Views
943
Activity
Jun ’26