Widgets & Live Activities

RSS for tag

Discuss how to manage and implement Widgets & Live Activities.

WidgetKit Documentation

Posts under Widgets & Live Activities subtopic

Post

Replies

Boosts

Views

Activity

iOS 26 WidgetKit APNs Pushes vs. NSE Targeted Reloads: Budget Allocation & Render Invalidation
Hello Apple DTS Team, We are optimizing a real-time iOS 26 WidgetKit architecture that utilizes both direct WidgetKit APNs pushes and Notification Service Extension (NSE) background asset downloading. We would appreciate technical clarification regarding budget allocation, execution latency, and view hierarchy invalidation on iOS 26. Architecture Overview Our system handles real-time visual updates across multiple distinct Widget kinds (KindA, KindB) using a dual-path pipeline: Direct WidgetKit APNs Push (iOS 26): Registers tokens via WidgetPushHandler (pushTokenDidChange(_:widgets:)). Remote server sends APNs requests targeting <bundleID>.push-type.widgets with apns-push-type: widgets and payload {"aps": {"content-changed": true}}. NSE Asset Pre-Fetch (Notification Service Extension): Server sends a remote notification containing mutable-content: 1 and asset metadata. The NSE intercepts the payload, streams the binary image asset into a shared App Group container (FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:)), writes JSON state to shared UserDefaults, and executes targeted timeline reloads via WidgetCenter.shared.reloadTimelines(ofKind: "KindA"). Timeline Provider: TimelineProvider.getTimeline() reads data synchronously from the shared App Group UserDefaults, resolves the local file path via UIImage(contentsOfFile:), and returns a single SimpleEntry with TimelineReloadPolicy.after(25 minutes) alongside TimelineEntryRelevance(score: 100.0). Technical Questions & Observed Behaviors Per-Kind Budget Isolation vs. Bundle-Wide Budget: Does dasd / chronod maintain an independent 70-reload daily budget for each individual Widget kind (or widget instance), or is the daily background reload budget shared globally across all widget kinds within the extension bundle? Does calling WidgetCenter.shared.reloadTimelines(ofKind: "KindA") from an NSE deduct budget tokens only from KindA's budget bucket, or does it deduct from a global shared bundle pool? NSE Reload Budget Deductions vs. Direct WidgetKit Pushes: Does a direct WidgetKit APNs push (apns-push-type: widgets) draw from a completely separate APNs push budget pool than a WidgetCenter.shared.reloadTimelines(ofKind:) call issued inside an NSE? When an NSE issues reloadTimelines(ofKind:) in response to a user-visible notification (alert + mutable-content: 1), does iOS grant notification grace tokens that bypass standard _DASWidgetBudget deductions? WidgetKit Push Notification Delivery & Rendering Inconsistencies on iOS 26: When sending direct WidgetKit APNs pushes (apns-push-type: widgets), we observe 3 distinct, inconsistent behaviors in production on iOS 26: a) Successful Instant Update: APNs push arrives → WidgetKit wakes up immediately → getTimeline() executes (<0.1s) → Home Screen widget displays the new image instantly. b) Complete Execution Drop: APNs push is sent by our server (HTTP 200 response from APNs api.push.apple.com) → WidgetKit never wakes up, and getTimeline() is completely ignored/not invoked by iOS. c) Execution Success but Screen Bitmap Stale: APNs push arrives → getTimeline() wakes up, executes, and loads the image successfully from disk (UIImage(contentsOfFile:) returns a valid image) → completion(Timeline(entries: [entry])) returns → BUT the displayed image on the Home Screen does NOT change or repaint until the user opens the main app. Questions for DTS Engineers: Why does iOS 26 occasionally drop getTimeline invocation for direct apns-push-type: widgets pushes even when APNs returns HTTP 200? Is Image(uiImage:) rendering inside WidgetKit subject to view hierarchy caching if the SimpleEntry struct date is updated but SwiftUI considers the view tree structurally identical? Does binding an explicit .id(assetPath) modifier to the Image view force SpringBoard's compositor layer to invalidate and repaint immediately upon getTimeline completion? Thank you for your guidance!
0
1
201
1w
AppIntent returned through result(opensIntent:) is not performed starting with iOS 27 Beta 3
I’m seeing a regression in the App Intents framework starting with iOS 27 Beta 3. An AppIntent returns another AppIntent using result(opensIntent:). On earlier iOS versions, the second intent’s perform() method is invoked as expected. Starting with iOS 27 Beta 3, the first intent completes, but the second intent’s perform() method is never called. Minimal example: import AppIntents import OSLog private let logger = Logger( subsystem: "com.example.AppIntentTest", category: "AppIntents" ) struct AAAIntent: AppIntent { static let title: LocalizedStringResource = "Run AAA" static let description = IntentDescription( "Runs AAA and returns BBB as the intent to open." ) func perform() async throws -> some IntentResult & OpensIntent { logger.notice("AAAIntent.perform() called") return .result(opensIntent: BBBIntent()) } } struct BBBIntent: AppIntent { static let title: LocalizedStringResource = "Run BBB" func perform() async throws -> some IntentResult { logger.notice("BBBIntent.perform() called") // The actual action would be performed here. return .result() } } Observed behavior on iOS 27 Beta 3: AAAIntent.perform() is called. AAAIntent.perform() returns .result(opensIntent: BBBIntent()). BBBIntent.perform() is never called. No error is presented to the user. Expected behavior: After AAAIntent returns BBBIntent through result(opensIntent:), the system should invoke BBBIntent.perform(), as it did on previous iOS versions. The same implementation works correctly on: before iOS 27 beta3 The issue reproduces on: Device: All iOS Device iOS: 27 Beta 3 I have also tested the following without resolving the problem: Reinstalling the app Recreating the shortcut Restarting the device Confirming through unified logging that BBBIntent.perform() is not entered This appears to be a system regression because the API remains available and the same application code works on earlier iOS versions. For required business logic, I can work around the problem by moving the shared operation out of BBBIntent.perform() and invoking it directly from AAAIntent. However, that changes the intended OpensIntent flow and does not restore the documented behavior of result(opensIntent:). I submitted this issue through Feedback Assistant two weeks ago: Feedback ID: FB23616137 Current Feedback Assistant status: Open Has anyone else encountered this behavior on iOS 27 Beta 3 or later? Is this a known App Intents regression, or has the expected behavior of result(opensIntent:) changed in iOS 27? If this behavior has intentionally changed, what is the recommended replacement for chaining or handing off to a second AppIntent?
0
0
138
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.
8
11
1.5k
1w
Live Activity (ActivityKit) always defaults to dark colorScheme on iOS 27
Environment: iOS Version: iOS 27.0 Framework: ActivityKit Xcode Version: Xcode 26.1 Issue Description: In iOS 27, Live Activities fail to adapt to the system colorScheme. Regardless of whether the system theme is set to Light or Dark mode, @Environment(.colorScheme) inside the Live Activity view always returns .dark. This behavior worked as expected on iOS 26, where the Live Activity correctly responded to light/dark mode changes and rendered the appropriate theme. Expected Behavior: The Live Activity view should respect the system's current colorScheme (returning .light when the system is in Light Mode) on iOS 27, consistent with the behavior on iOS 26. Actual Behavior: The Live Activity view strictly defaults to .dark mode on iOS 27, even when the device is explicitly set to Light Mode. struct LockScreenView<T: BaseLiveActivityAttributes>: View { let context: ActivityViewContext<T> @Environment(\.colorScheme) var colorScheme var isLight: Bool { colorScheme == .light } var body: some View { Color(isLight ? .white : .black) .overlay(alignment: .topTrailing) { VStack(alignment: .trailing, spacing: 2) { Text("colorScheme: \(String(describing: colorScheme))") } .font(.system(size: 9, weight: .bold, design: .monospaced)) .foregroundColor(.yellow) .padding(4) .background(Color.black.opacity(0.6)) .cornerRadius(4) .padding(.trailing, 8) .padding(.top, 4) } } } Any insights or workarounds would be greatly appreciated. Thanks!
0
0
216
1w
Lack of Native CJK Serif Font Support in WidgetKit (Font.design(.serif))
Hello everyone, I am encountering an inconsistent typography behavior when developing for WidgetKit. Specifically, there is no native serif font fallback for Chinese characters (CJK) in the Widget environment, whereas Latin characters are fully supported. When using the .serif design modifier in SwiftUI: Text("Hello 世界").font(.system(size: 16, design: .serif)) English/Latin characters ("Hello"): System correctly renders using the pre-installed serif font (New York). Chinese characters ("世界"): System ignores the .serif design and falls back to the default sans-serif font (PingFang SC). Can I find any pre-installed native serif font for CJK in iOS that I can reliably invoke within my Widget Extension without bundling .ttf files? If not, do you have plans to map Font.design(.serif) to a pre-installed CJK serif font in future iOS releases so I can maintain design consistency across my localized widgets? Thank you for any insights or recommended workarounds.
0
0
290
2w
WidgetKit complications won't update
We are migrating ClockKit complications to WidgetKit in our watch app (watchOS 9+). The migration went smoothly, UI part works just fine. However, we've hit the wall with widgets not updating when requested by the watch app. I believe we are missing something very simple and fundamental, but couldn't find what exactly so far. Advice and tips would be very welcome! 🙇‍♂️ Our implementation details: Whenever data is changed in the main app, the updated data is submitted to the watch app via WatchConnectivity framework using WCSession.default.transferCurrentComplicationUserInfo(_:). According to documentation, this method should be used to transfer complication-related data, since it will wake the watch app even if it is in the background or not opened at all. Watch app receives updated data and stores it in UserDefaults shared with Watch Widget Extension hosting WidgetKit complications via App Group. Watch app then request widget timeline reload via WidgetCenter.shared.reloadAllTimelines(). According to documentation, it reloads the timelines for all configured widgets belonging to the containing app, so it seems the appropriate way to reload WidgetKit complications. Widget Timeline Provider class in Watch Widget Extension reads updated data from shared UserDefaults and uses it to provide the updated snapshot for widget views to render. We believe our implementation logic is correct, but it doesn't work, for some reason. Widgets sometimes update when the watch app is opened, but not always. The most definitive way to force widgets to update is to switch to a different watch face, which confirms that the Widget Timeline Provider has access to properly updated data. P.S. We are aware of the daily reload budget imposed on widgets, so we use widgets reload trigger sparingly. Anyway, according to documentation, reload budget is not effective when in DEBUG mode, but widgets won't reload even in DEBUG mode. Thank you!
20
10
8.1k
3w
AudioRecordingIntent: AVAudioSession.setActive() fails with OSStatus 561015905 on Lock Screen
Hello, I'm implementing AudioRecordingIntent on iOS 26. My goal is to support Action Button exactly like Apple's Voice Memos: • press Action Button • device remains locked • recording starts immediately • no Face ID • Live Activity is shown • no application UI My intent conforms to AudioRecordingIntent. Inside perform() I do: AVAudioSession.sharedInstance().setCategory(.record) AVAudioSession.sharedInstance().setActive(true) AVAudioRecorder.record() The result is: setCategory succeeds. setActive always fails with NSOSStatusErrorDomain Code = 561015905 "Session activation failed" The failure happens before AVAudioRecorder starts. If I instead forward execution to the main application, iOS requests Face ID before recording begins. Questions: Is AVAudioSession activation inside AudioRecordingIntent actually supported for third-party apps? If not, what is the expected architecture for implementing lock-screen recording using AudioRecordingIntent? Is there an official sample project demonstrating the intended implementation? Thank you.
0
0
394
4w
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
672
Jul ’26
Widget and Core Data with CloudKit
I have two apps that use App Groups, CloudKit and Core Data for sharing data between multiple devices and users (one is a sample for the issue, the other one the full fledged one). In the sample app I have the following model: Collection (name) -> many Items (names and count) and corresponding views to increment the count. I also have the widget share the proper App Group and CloudKit container. It has a button that triggers an increment app intent. A create a shared collection "Shares" and add two items in it - "A" & "B". Sharing from the applications and updates of the count takes about 2 seconds. I.e. I open the item view and I tap an increment button, the second phone screen updates almost immediately. Upon each update I also call WidgetCenter.shared.reloadAllTimelines(). What I see is that widgets have are not in sync with the data of the app. I have an explicit button to trigger the reload of the timelines, I can follow along with the debugger and the Core Data data is different, i.e. different count. I also show a date property, so I know that the widget is redrawn. I think that as soon as I added the target for the widget and added it to the app group I started seeing: BUG IN CLOUDKIT: Error submitting background task request: Error Domain=BGSystemTaskSchedulerErrorDomain Code=3 "(null)". The sync between the widget and the app on the same device is inconsistent. I also see a lot of when interactions happen fast. submitTaskRequest failed for com.apple.coredata.cloudkit.activity.import. submitTaskRequest failed for com.apple.coredata.cloudkit.activity.export. I least I hope is that after the app has synchronised, the widget will catch-up and show the same data - i.e. at least the same device will show data consistently. This does not happen though. Even on the device on which I'm doing the changes, and tapping multiple times the manual reload of widgets button, the Core Data is stale, and the time of reload of the widget is fine. The relevant threads this I've found are (none of them can shed any light): https://developer.apple.com/forums/thread/653112?answerId=697974022 https://developer.apple.com/forums/thread/650192?answerId=614112022#614112022 https://developer.apple.com/forums/thread/651648?answerId=827386022 I have tested with iOS 26.5.2 and iOS 27 Beta. The widget is it out sync
2
0
513
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.2k
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
449
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.1k
Jun ’26
LiveActivity push-to-start flow inconsistency
Problem: unable to retrieve push-to-start token upon app start Environment: simulator, iPhone 15 Pro, iOS 18.1 (also reproduced on physical devices) First image is a start from XCode with "Run" option (Cmd+R) where debugger is linked Second image is a "cold" start - starting app by tapping the icon Difference is: Start observing (line 2), push token changed (last line). Everything is okay Push token changed (7 line), start observing (9 line). liveactivitysd generates token before we reach pushToStartTokenUpdates loop - we losing token The question is: how is this possible (case 2)?
0
0
437
Jun ’26
iOS 26.5 breaks AppIntents with AppEnums defined in Swift Package
For some reason since iOS 26.5, a ControlWidgetButton or a Button in a widget configured with an AppIntent conforming to OpenIntent fails to receive its AppEnum parameter correctly if the intent and enum are defined inside a shared Swift Package. Tapping the control widget button opens the main application, but it doesn't pass the AppEnum parameter value in, leaving the app on its default screen instead of navigating to the intended view. This was working perfectly in iOS 26.4, where the app would launch and receive the correct enum case from the intent. No code, configuration, or scheme changes were made between the two runs, only the simulator/OS version differs. Has anyone else run into what seems to be a regression on iOS 26.5? I filed feedback with a sample project: FB22848510
1
2
873
Jun ’26
How can I get Apple Clips
I saw Apple Clips on one of my relatives phone but it’s discontinued now so how do I download it without the family thing and the Apple ID?
Replies
0
Boosts
0
Views
103
Activity
6d
iOS 26 WidgetKit APNs Pushes vs. NSE Targeted Reloads: Budget Allocation & Render Invalidation
Hello Apple DTS Team, We are optimizing a real-time iOS 26 WidgetKit architecture that utilizes both direct WidgetKit APNs pushes and Notification Service Extension (NSE) background asset downloading. We would appreciate technical clarification regarding budget allocation, execution latency, and view hierarchy invalidation on iOS 26. Architecture Overview Our system handles real-time visual updates across multiple distinct Widget kinds (KindA, KindB) using a dual-path pipeline: Direct WidgetKit APNs Push (iOS 26): Registers tokens via WidgetPushHandler (pushTokenDidChange(_:widgets:)). Remote server sends APNs requests targeting <bundleID>.push-type.widgets with apns-push-type: widgets and payload {"aps": {"content-changed": true}}. NSE Asset Pre-Fetch (Notification Service Extension): Server sends a remote notification containing mutable-content: 1 and asset metadata. The NSE intercepts the payload, streams the binary image asset into a shared App Group container (FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:)), writes JSON state to shared UserDefaults, and executes targeted timeline reloads via WidgetCenter.shared.reloadTimelines(ofKind: "KindA"). Timeline Provider: TimelineProvider.getTimeline() reads data synchronously from the shared App Group UserDefaults, resolves the local file path via UIImage(contentsOfFile:), and returns a single SimpleEntry with TimelineReloadPolicy.after(25 minutes) alongside TimelineEntryRelevance(score: 100.0). Technical Questions & Observed Behaviors Per-Kind Budget Isolation vs. Bundle-Wide Budget: Does dasd / chronod maintain an independent 70-reload daily budget for each individual Widget kind (or widget instance), or is the daily background reload budget shared globally across all widget kinds within the extension bundle? Does calling WidgetCenter.shared.reloadTimelines(ofKind: "KindA") from an NSE deduct budget tokens only from KindA's budget bucket, or does it deduct from a global shared bundle pool? NSE Reload Budget Deductions vs. Direct WidgetKit Pushes: Does a direct WidgetKit APNs push (apns-push-type: widgets) draw from a completely separate APNs push budget pool than a WidgetCenter.shared.reloadTimelines(ofKind:) call issued inside an NSE? When an NSE issues reloadTimelines(ofKind:) in response to a user-visible notification (alert + mutable-content: 1), does iOS grant notification grace tokens that bypass standard _DASWidgetBudget deductions? WidgetKit Push Notification Delivery & Rendering Inconsistencies on iOS 26: When sending direct WidgetKit APNs pushes (apns-push-type: widgets), we observe 3 distinct, inconsistent behaviors in production on iOS 26: a) Successful Instant Update: APNs push arrives → WidgetKit wakes up immediately → getTimeline() executes (<0.1s) → Home Screen widget displays the new image instantly. b) Complete Execution Drop: APNs push is sent by our server (HTTP 200 response from APNs api.push.apple.com) → WidgetKit never wakes up, and getTimeline() is completely ignored/not invoked by iOS. c) Execution Success but Screen Bitmap Stale: APNs push arrives → getTimeline() wakes up, executes, and loads the image successfully from disk (UIImage(contentsOfFile:) returns a valid image) → completion(Timeline(entries: [entry])) returns → BUT the displayed image on the Home Screen does NOT change or repaint until the user opens the main app. Questions for DTS Engineers: Why does iOS 26 occasionally drop getTimeline invocation for direct apns-push-type: widgets pushes even when APNs returns HTTP 200? Is Image(uiImage:) rendering inside WidgetKit subject to view hierarchy caching if the SimpleEntry struct date is updated but SwiftUI considers the view tree structurally identical? Does binding an explicit .id(assetPath) modifier to the Image view force SpringBoard's compositor layer to invalidate and repaint immediately upon getTimeline completion? Thank you for your guidance!
Replies
0
Boosts
1
Views
201
Activity
1w
iOS 27 beta Widget can not be found in gallery
After the installation and upgrade of the iOS App coverage, the desktop widget became unavailable. When deleting and re-adding them, they could not be found in the widget gallery . The problem was solved after the phone system was restarted
Replies
0
Boosts
0
Views
195
Activity
1w
AppIntent returned through result(opensIntent:) is not performed starting with iOS 27 Beta 3
I’m seeing a regression in the App Intents framework starting with iOS 27 Beta 3. An AppIntent returns another AppIntent using result(opensIntent:). On earlier iOS versions, the second intent’s perform() method is invoked as expected. Starting with iOS 27 Beta 3, the first intent completes, but the second intent’s perform() method is never called. Minimal example: import AppIntents import OSLog private let logger = Logger( subsystem: "com.example.AppIntentTest", category: "AppIntents" ) struct AAAIntent: AppIntent { static let title: LocalizedStringResource = "Run AAA" static let description = IntentDescription( "Runs AAA and returns BBB as the intent to open." ) func perform() async throws -> some IntentResult & OpensIntent { logger.notice("AAAIntent.perform() called") return .result(opensIntent: BBBIntent()) } } struct BBBIntent: AppIntent { static let title: LocalizedStringResource = "Run BBB" func perform() async throws -> some IntentResult { logger.notice("BBBIntent.perform() called") // The actual action would be performed here. return .result() } } Observed behavior on iOS 27 Beta 3: AAAIntent.perform() is called. AAAIntent.perform() returns .result(opensIntent: BBBIntent()). BBBIntent.perform() is never called. No error is presented to the user. Expected behavior: After AAAIntent returns BBBIntent through result(opensIntent:), the system should invoke BBBIntent.perform(), as it did on previous iOS versions. The same implementation works correctly on: before iOS 27 beta3 The issue reproduces on: Device: All iOS Device iOS: 27 Beta 3 I have also tested the following without resolving the problem: Reinstalling the app Recreating the shortcut Restarting the device Confirming through unified logging that BBBIntent.perform() is not entered This appears to be a system regression because the API remains available and the same application code works on earlier iOS versions. For required business logic, I can work around the problem by moving the shared operation out of BBBIntent.perform() and invoking it directly from AAAIntent. However, that changes the intended OpensIntent flow and does not restore the documented behavior of result(opensIntent:). I submitted this issue through Feedback Assistant two weeks ago: Feedback ID: FB23616137 Current Feedback Assistant status: Open Has anyone else encountered this behavior on iOS 27 Beta 3 or later? Is this a known App Intents regression, or has the expected behavior of result(opensIntent:) changed in iOS 27? If this behavior has intentionally changed, what is the recommended replacement for chaining or handing off to a second AppIntent?
Replies
0
Boosts
0
Views
138
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
8
Boosts
11
Views
1.5k
Activity
1w
Live Activity (ActivityKit) always defaults to dark colorScheme on iOS 27
Environment: iOS Version: iOS 27.0 Framework: ActivityKit Xcode Version: Xcode 26.1 Issue Description: In iOS 27, Live Activities fail to adapt to the system colorScheme. Regardless of whether the system theme is set to Light or Dark mode, @Environment(.colorScheme) inside the Live Activity view always returns .dark. This behavior worked as expected on iOS 26, where the Live Activity correctly responded to light/dark mode changes and rendered the appropriate theme. Expected Behavior: The Live Activity view should respect the system's current colorScheme (returning .light when the system is in Light Mode) on iOS 27, consistent with the behavior on iOS 26. Actual Behavior: The Live Activity view strictly defaults to .dark mode on iOS 27, even when the device is explicitly set to Light Mode. struct LockScreenView<T: BaseLiveActivityAttributes>: View { let context: ActivityViewContext<T> @Environment(\.colorScheme) var colorScheme var isLight: Bool { colorScheme == .light } var body: some View { Color(isLight ? .white : .black) .overlay(alignment: .topTrailing) { VStack(alignment: .trailing, spacing: 2) { Text("colorScheme: \(String(describing: colorScheme))") } .font(.system(size: 9, weight: .bold, design: .monospaced)) .foregroundColor(.yellow) .padding(4) .background(Color.black.opacity(0.6)) .cornerRadius(4) .padding(.trailing, 8) .padding(.top, 4) } } } Any insights or workarounds would be greatly appreciated. Thanks!
Replies
0
Boosts
0
Views
216
Activity
1w
Lack of Native CJK Serif Font Support in WidgetKit (Font.design(.serif))
Hello everyone, I am encountering an inconsistent typography behavior when developing for WidgetKit. Specifically, there is no native serif font fallback for Chinese characters (CJK) in the Widget environment, whereas Latin characters are fully supported. When using the .serif design modifier in SwiftUI: Text("Hello 世界").font(.system(size: 16, design: .serif)) English/Latin characters ("Hello"): System correctly renders using the pre-installed serif font (New York). Chinese characters ("世界"): System ignores the .serif design and falls back to the default sans-serif font (PingFang SC). Can I find any pre-installed native serif font for CJK in iOS that I can reliably invoke within my Widget Extension without bundling .ttf files? If not, do you have plans to map Font.design(.serif) to a pre-installed CJK serif font in future iOS releases so I can maintain design consistency across my localized widgets? Thank you for any insights or recommended workarounds.
Replies
0
Boosts
0
Views
290
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
348
Activity
2w
Control Center and other music apps
Now, my app "iSwitcher" can switch songs only in Apple Music. How to switch songs in any app that are playing? It is available in Android system.
Replies
1
Boosts
0
Views
327
Activity
3w
WidgetKit complications won't update
We are migrating ClockKit complications to WidgetKit in our watch app (watchOS 9+). The migration went smoothly, UI part works just fine. However, we've hit the wall with widgets not updating when requested by the watch app. I believe we are missing something very simple and fundamental, but couldn't find what exactly so far. Advice and tips would be very welcome! 🙇‍♂️ Our implementation details: Whenever data is changed in the main app, the updated data is submitted to the watch app via WatchConnectivity framework using WCSession.default.transferCurrentComplicationUserInfo(_:). According to documentation, this method should be used to transfer complication-related data, since it will wake the watch app even if it is in the background or not opened at all. Watch app receives updated data and stores it in UserDefaults shared with Watch Widget Extension hosting WidgetKit complications via App Group. Watch app then request widget timeline reload via WidgetCenter.shared.reloadAllTimelines(). According to documentation, it reloads the timelines for all configured widgets belonging to the containing app, so it seems the appropriate way to reload WidgetKit complications. Widget Timeline Provider class in Watch Widget Extension reads updated data from shared UserDefaults and uses it to provide the updated snapshot for widget views to render. We believe our implementation logic is correct, but it doesn't work, for some reason. Widgets sometimes update when the watch app is opened, but not always. The most definitive way to force widgets to update is to switch to a different watch face, which confirms that the Widget Timeline Provider has access to properly updated data. P.S. We are aware of the daily reload budget imposed on widgets, so we use widgets reload trigger sparingly. Anyway, according to documentation, reload budget is not effective when in DEBUG mode, but widgets won't reload even in DEBUG mode. Thank you!
Replies
20
Boosts
10
Views
8.1k
Activity
3w
AudioRecordingIntent: AVAudioSession.setActive() fails with OSStatus 561015905 on Lock Screen
Hello, I'm implementing AudioRecordingIntent on iOS 26. My goal is to support Action Button exactly like Apple's Voice Memos: • press Action Button • device remains locked • recording starts immediately • no Face ID • Live Activity is shown • no application UI My intent conforms to AudioRecordingIntent. Inside perform() I do: AVAudioSession.sharedInstance().setCategory(.record) AVAudioSession.sharedInstance().setActive(true) AVAudioRecorder.record() The result is: setCategory succeeds. setActive always fails with NSOSStatusErrorDomain Code = 561015905 "Session activation failed" The failure happens before AVAudioRecorder starts. If I instead forward execution to the main application, iOS requests Face ID before recording begins. Questions: Is AVAudioSession activation inside AudioRecordingIntent actually supported for third-party apps? If not, what is the expected architecture for implementing lock-screen recording using AudioRecordingIntent? Is there an official sample project demonstrating the intended implementation? Thank you.
Replies
0
Boosts
0
Views
394
Activity
4w
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
672
Activity
Jul ’26
Widget and Core Data with CloudKit
I have two apps that use App Groups, CloudKit and Core Data for sharing data between multiple devices and users (one is a sample for the issue, the other one the full fledged one). In the sample app I have the following model: Collection (name) -> many Items (names and count) and corresponding views to increment the count. I also have the widget share the proper App Group and CloudKit container. It has a button that triggers an increment app intent. A create a shared collection "Shares" and add two items in it - "A" & "B". Sharing from the applications and updates of the count takes about 2 seconds. I.e. I open the item view and I tap an increment button, the second phone screen updates almost immediately. Upon each update I also call WidgetCenter.shared.reloadAllTimelines(). What I see is that widgets have are not in sync with the data of the app. I have an explicit button to trigger the reload of the timelines, I can follow along with the debugger and the Core Data data is different, i.e. different count. I also show a date property, so I know that the widget is redrawn. I think that as soon as I added the target for the widget and added it to the app group I started seeing: BUG IN CLOUDKIT: Error submitting background task request: Error Domain=BGSystemTaskSchedulerErrorDomain Code=3 "(null)". The sync between the widget and the app on the same device is inconsistent. I also see a lot of when interactions happen fast. submitTaskRequest failed for com.apple.coredata.cloudkit.activity.import. submitTaskRequest failed for com.apple.coredata.cloudkit.activity.export. I least I hope is that after the app has synchronised, the widget will catch-up and show the same data - i.e. at least the same device will show data consistently. This does not happen though. Even on the device on which I'm doing the changes, and tapping multiple times the manual reload of widgets button, the Core Data is stale, and the time of reload of the widget is fine. The relevant threads this I've found are (none of them can shed any light): https://developer.apple.com/forums/thread/653112?answerId=697974022 https://developer.apple.com/forums/thread/650192?answerId=614112022#614112022 https://developer.apple.com/forums/thread/651648?answerId=827386022 I have tested with iOS 26.5.2 and iOS 27 Beta. The widget is it out sync
Replies
2
Boosts
0
Views
513
Activity
Jul ’26
Hotspot not disabled on control center through the widget with multiple network
Hotspot not being disabled through the widget with multiple network buttons (dont remember the name of it, it has multiple connection widgets as one). The hotspot is however is shown disabled but its not the correct state as we can discover in settings that is still enabled.
Replies
1
Boosts
0
Views
437
Activity
Jun ’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.2k
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
449
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.1k
Activity
Jun ’26
LiveActivity push-to-start flow inconsistency
Problem: unable to retrieve push-to-start token upon app start Environment: simulator, iPhone 15 Pro, iOS 18.1 (also reproduced on physical devices) First image is a start from XCode with "Run" option (Cmd+R) where debugger is linked Second image is a "cold" start - starting app by tapping the icon Difference is: Start observing (line 2), push token changed (last line). Everything is okay Push token changed (7 line), start observing (9 line). liveactivitysd generates token before we reach pushToStartTokenUpdates loop - we losing token The question is: how is this possible (case 2)?
Replies
0
Boosts
0
Views
437
Activity
Jun ’26
iOS 26.5 breaks AppIntents with AppEnums defined in Swift Package
For some reason since iOS 26.5, a ControlWidgetButton or a Button in a widget configured with an AppIntent conforming to OpenIntent fails to receive its AppEnum parameter correctly if the intent and enum are defined inside a shared Swift Package. Tapping the control widget button opens the main application, but it doesn't pass the AppEnum parameter value in, leaving the app on its default screen instead of navigating to the intended view. This was working perfectly in iOS 26.4, where the app would launch and receive the correct enum case from the intent. No code, configuration, or scheme changes were made between the two runs, only the simulator/OS version differs. Has anyone else run into what seems to be a regression on iOS 26.5? I filed feedback with a sample project: FB22848510
Replies
1
Boosts
2
Views
873
Activity
Jun ’26
KEEP WALKIE TALKIE
Pls apple i daily drive this and is a core part of the apple ecosystem i even bought my cousin a watch to solely talk to him whenever
Replies
1
Boosts
0
Views
480
Activity
Jun ’26