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

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
87
2d
Complication flickers in Infograph sub-dials on a single-color Infograph face with Always On (watchOS 27)
On watchOS 27 my app's round complication on the Infograph face disappears for about a second every time I raise or lower my wrist, then comes back. It only happens in the small round dials of that face, only when the face is set to a single color instead of Multicolor, and only when Always On Display is turned on. Everything else on the same watch is fine. my complication placed in a corner of the same face, the same face set to Multicolor, and an Apple complication sitting right next to mine. Other faces set to a single color are fine too, including in their round slots - I tested Modular and Meridian among others. With Always On Display off there is no problem either. What I already checked is: It still happens when my complication is the only one on the face. It still happens when the complication shows just a single line of plain text. The data is not being reloaded. I displayed the timestamp of the entry inside the complication and it does not change across the gap, so the same content is simply being redrawn. Removing the complication and adding it back does not help. Rebuilding with the newest Xcode changes nothing, and an older build behaves exactly the same. The same app, unchanged, worked correctly on watchOS 26. This started right after updating the watch to watchOS 27. Has anyone else run into this on watchOS 27? And has anyone found anything on the app side that makes a difference? I have not found a single thing.
0
0
113
4d
iOS Dynamically loaded custom fonts in WidgetKit not working on real device (simulator is fine). Sandbox chronod deny file-read-data for font file.
Project structure is: App target + widget extension + widget intent extension All share a common appgroup group.com.x.y and all file handling is done using FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.x.y") so that only the shared container is used. Using the Main app target, a font "Chewy-Regular.ttf" is downloaded and saved to the shared AppGroup container. Font can now be loaded via CTFontManagerRegisterFontsForURL and displayed in a Main App Text view Text("Testing...").font(Font.custom("Chewy-Regular", size: 20)) Now add a Widgetkit widget instance that uses this font. In 'getTimeLine() and getSnapShot() of IntentTimelineProvider we load the font again via CTFontManagerRegisterFontsForURL (this needs to happen again probably because widget runs in a separate process from the main app?). On simulator, the widget will show the correct font. BUT On iPhone7 real device, the widget will show the 'redacted placeholder view'. It seems that something is crashing. I see in the device console : error 14:39:07.567120-0800 chronod No configuration found for configured widget identifier: D9BF75EE-4A04-441A-8C85-1507F7ECE379 fault 14:39:07.625600-0800 widgetxExtension -[EXSwiftUI_Subsystem beginUsing:withBundle:] unexpectedly called multiple times. error 14:39:07.672733-0800 chronod Encountered an error reading the view archive for <private>; error: <private> error 14:39:07.672799-0800 chronod [co.appevolve.onewidget.widgetx:widgetx:small:1536744920620481560@148.0/148.0/20.2] reload: could not decode view error 14:39:07.674984-0800 kernel Sandbox: chronod(2128) deny(1) file-read-metadata /private/var/mobile/Containers/Shared/AppGroup/9B524570-1765-4C24-9E0C-15BC3982F0DC/downloadedFonts/Chewy/Chewy-Regular.ttf error 14:39:07.675762-0800 kernel Sandbox: chronod(2128) deny(1) file-read-data /private/var/mobile/Containers/Shared/AppGroup/9B524570-1765-4C24-9E0C-15BC3982F0DC/downloadedFonts/Chewy/Chewy-Regular.ttf error 14:39:07.708914-0800 chronod [u 8D2C83B3-A6CB-432E-A9D4-9BC8F7056B10:m (null)] [<private>(<private>)] Connection to plugin invalidated while in use. fault 14:39:07.710284-0800 widgetxExtension -[EXSwiftUI_Subsystem beginUsing:withBundle:] unexpectedly called multiple times. error 14:39:07.803468-0800 chronod Encountered an error reading the view archive for <private>; error: <private> It seems that it's a permission issue, and the textview can't access the font file it needs when the widget is rendering. Notes: 1) Font is definitely registered because I can see them in for fontFamily in UIFont.familyNames {             for fontName in UIFont.fontNames(forFamilyName: fontFamily) {                 print(fontName) 								... in both the Main App target and the Widget Extension target 2) If I make make the font part of the app bundle and add to 'Fonts provided by application' , the are loaded absolutely fine in the Main App and the Widget on simulator and iPhone 7 real device. 3) I do see this error sometimes in the Widget extension target log, don't know if it's related. widgetxExtension[1385:254599] [User Defaults] Couldn't read values in CFPrefsPlistSource<0x28375b880> (Domain: group.co.appevolve.onewidget, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd 4) I suspected something to do with app groups, so I tried to copy the font into the Widget Extension container and load from there, but had the same result. Please help! Thank you.
8
1
3.5k
6d
Semantic Wallet Boarding Pass - Missing airport details ( Gate & terminal) for some airports
Hi team, We've successfully implemented Semantic wallet boarding passes. However, the flight details (gate and terminal) are not appearing for some airports ex: MCT, possibly because this information is not available in Apple’s flight data source. We would like to understand how these details can be kept up to date in Apple’s data source so that they are correctly reflected on the boarding pass. Thank you! Haya
0
0
282
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
1w
watchOS 27 beta: EVERY app update kills WidgetKit complications until the watch is rebooted
Filed as FB24619522 — sysdiagnoses from both devices and the live logs are attached to the report. We ship WidgetKit complications, and on the watchOS 27 betas (24R5360a, paired with iOS 27 24A5430a) they die every time the app gets updated while they're on the active face. Within seconds they turn into empty placeholders and never come back on their own — opening the app, switching faces or reloading timelines from the app does nothing. The watch logs show the extension being killed during the install (normal), and after that watchOS simply can't launch the new copy any more: runningboardd: <OSLaunchdJob | handle=…>: start succeeded, info=spawn failed, error=111: Invalid or missing Program/ProgramArguments chronod(ChronoKit): Reload failed; 0 retries remaining: … "Unknown extension process" Only two things fix it, and both restart chronod: rebooting the watch, or switching the watch language and back (iPhone › Watch app › General › Language & Region, then give it a couple of minutes). Our second extension in the same bundle, which wasn't running during the install, came back fine — so this looks like an OS bug rather than something we can work around in code. iOS 27 widgets seem to have the same problem (this thread, and iPhone in Canada wrote it up on beta 4), and someone posted the identical log lines back in March. FB24619522 — the full story, both sysdiagnoses and the live logs are in the Feedback.
0
3
437
1w
Live Activity PushType.channel updates silently not delivered on some devices, despite successful activity creation
Hi all, We're seeing an issue where Live Activity content-state push updates sent via PushType.channel(_:) are not consistently delivered to all devices subscribed to the same channel — even though Activity.request() succeeds on every device, and the affected/unaffected devices are both on recent iOS versions well above the 18.1 minimum for channel-based push. Setup: Our backend broadcasts content-state updates to all devices subscribed to a given channel. Activity creation succeeds normally on the affected device, but it never receives a single subsequent update — the activity eventually goes .stale after its staleDate elapses, despite our backend confirming it sent an update to that channel. What we've verified so far: Activity.request() succeeds locally on the affected device, no error thrown. We instrument ContentState's Decodable init(from decoder:) to log every time ActivityKit attempts to decode an incoming push. On the affected device, this log never fires — so no push payload is ever being handed to ActivityKit at all on that device. It's not a decode/payload-format issue. A second device on the identical app build and channel setup receives updates normally in the same window — rules out a backend-wide outage. Both devices are on recent iOS (affected: iPhone 13 Pro Max, iOS 26.5.2 / unaffected: iPhone 15 Pro Max, iOS 26.6) — rules out OS version threshold. No logs, crash reports, or console output of any kind on the affected device around when the update should have arrived — completely silent failure. Question: Has anyone run into a device silently failing to receive PushType.channel broadcast updates like this? Are there known conditions (notification permissions, Low Power Mode, Background App Refresh, channel subscription expiry/limits, etc.) that could cause this? Is there any client-side API to check the health/status of a device's channel subscription, to distinguish "not subscribed," "subscription expired," and "subscribed but delivery failed"? Any pointers appreciated — happy to share more details if useful.
0
0
326
2w
WidgetKit timeline crashes with EXC_RESOURCE (memory limit=30MB) when generating entries from a large photo album
Environment: Xcode 15/16, iOS 17/18, WidgetKit (IntentTimelineProvider) Issue: I have a photo widget that lets users pick an album and rotate through its photos on a timer (configurable refresh interval). When the selected album is large, the widget extension is Jetsam-killed with: Thread X: EXC_RESOURCE (RESOURCE_TYPE_MEMORY: high watermark memory limit exceeded) (limit=30 MB) After this happens, the widget stops refreshing entirely and stays on a stale/placeholder image until the app is relaunched. What I've tried: Downsampling with CGImageSourceCreateThumbnailAtIndex + kCGImageSourceThumbnailMaxPixelSize before building entries Reducing entry count and using policy .after(nextDate) instead of pre-building a full day of entries Still seeing intermittent Jetsams on albums with several hundred photos Questions: Is there a recommended max total archived timeline size WidgetKit expects developers to stay under, beyond "keep it small"? For a "large photo album" use case specifically, is the recommended pattern to pre-generate and cache small thumbnails in the App Group container ahead of time, rather than downsampling on demand inside getTimeline()? Is there guidance on how many timeline entries is "too many" before WidgetKit itself starts struggling to archive/deliver them, independent of image size? useful than a forum thread — let me know what info would help most.
0
0
228
3w
Widget is crashing with 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=30 MB, unused=0x0)
I have created widget which supports medium and large family similar to news feed app like title and image by configuring the medium widget with 2 articles and large with 4 articles where each article has title and it's image with size 46x46 and 61x61. When am adding the small and large widgets to my Home Screen getting memory limit (Thread 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=30 MB, unused=0x0)(crash and the widget is not refreshing and some times widgets is showing the skeletons instead of data. This is my timeline provider     func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) {             widgetVM.getRecommendedDataForWidget{ (result) in                 switch result {                 case .success(let items):                     let entries =  getRecommendedWidgetTimeLineEntries(recFeedModel: items)                     let timeline = Timeline(entries: entries, policy: .atEnd)                     completion(timeline)                 case .failure(_):                         let entry = RecommendedWidgetEntry(date: Date(), recommedationData: WidgetFeedModel.getPlaceholderData())                         let timeline = Timeline(entries: [entry], policy: .never)                         completion(timeline)                 }             }         }         else {             if accessTokenValue == nil { // if token is nil then considering it as member is not logged in.                 let entry = RecommendedWidgetEntry(date: Date(), recommedationData: [])                 let timeline = Timeline(entries: [entry], policy: .never)                 completion(timeline)                 return             }     } Could you please help me out on this as this is priority for me as part of app release. I couldn't find out the reason for this. Thanks
10
0
4.4k
3w
AlarmKit Bug: Dismissing the alarm by touching the bottom notch area.
This is about AlarmKit, and this problem is also happening with the native phone alarm. I’m working on some alarm apps, and some users have been complaining that when they get their phone, the alarm is being dismissed. We were never able to simulate this until today. We noticed that when touching the bottom notch of the phone, below the stop swipe area, sometimes the alarm is simply dismissed. In some cases, you can see the same UI repeated behind the screen; other times, you can’t drag, but it also dismisses the alarm. This seems to have been happening for quite a while with our users. They grab their phones, unintentionally touch that area, and dismiss the alarm. It’s very critical for us because we present other buttons on AlarmKit for the user to click on (guess which bird is singing, for example). Feedback Ticket Created: FB24407814
1
0
520
3w
Custom icons or background imagery for App Shortcut tiles in the Shortcuts app?
Hi — I’m trying to understand what customization is currently supported for App Shortcuts as they appear inside the Shortcuts app. From the public App Intents APIs, it looks like an AppShortcut can specify a systemImageName, and an AppShortcutsProvider can specify a shortcutTileColor. I haven’t been able to find documentation for either of the following: Using a custom app-provided icon/image asset instead of an SF Symbol Using custom imagery or a background image for the App Shortcut tile itself However, some Apple apps such as Music and Podcasts appear to use richer/custom artwork in their Shortcuts tiles, which made me wonder whether there is a supported API or approach that I’m missing. Are custom icons or background images currently supported for App Shortcut tiles through public APIs? If not, are the richer treatments used by Apple Music/Podcasts based on system-only capabilities that aren’t currently available to third-party apps? Thanks!
0
0
247
4w
Widget Extension still uses system language even though CFBundleAllowMixedLocalizations = NO is set
I have an app with a Widget Extension. Both the main app and the widget extension link against the same Swift Package, which contains a localization bundle (String Catalog) used by SwiftUI views inside the package. To make the package's views follow the app's configured language (rather than the system language), I set CFBundleAllowMixedLocalizations to NO in the Info.plist of each target (main app and widget extension). Behavior in the main app: This works as expected. If the app only supports Korean, the package's views display Korean text even when the system language is set to English. Behavior in the widget: The same views (from the same package) display English instead of Korean, even though the widget extension has the identical CFBundleAllowMixedLocalizations = NO setting and the widget's view code lives entirely in the package — not in the widget extension target itself. Question: As far as I understand, widgets are supposed to follow the host app's language setting. Given that both targets have the same Info.plist configuration, why would the widget extension resolve localized strings differently from the main app for code in the same package? Is this expected behavior for widget extensions specifically, or a bug? Is there a recommended workaround to force a widget extension (and by extension, the Swift Package code it runs) to use the app's language instead of the system language?
1
0
946
Aug ’26
On vision 27, accessoryRectangular shows blank
Hi, On visionOS 27 simulator accessoryRectangular widget shows completely blank with no text. The same widget shows up correctly on iOS 27 simulator. What I have tried: I have checked the timeline provider and they all seem to be generating timeline entries. supportedFamilies include accessoryRectangular I have even hard coded the content in the view for the widget yet only accessoryRectangular for visionOS 27 shows up blank. Isolated problem The same widget shows up correctly on iOS 27 simulator. The problem is only with visionOS 27. Environment: macOS: 26.6.1 (25G76) Xcode: 27.0 beta 5 (27A5237l) Simulator: visionOS 27.0 Questions What am I missing? How can I resolve it? Is this a known issue? Has anyone gotten accessoryRectangular widget showing up on visionOS 27 simulator? Any help on this would be much appreciated.
0
0
473
Aug ’26
Is it recommended to use Foundation Model's SystemLanguageModel directly in a WidgetKit extension?
I'm exploring the possibility of using Apple's SystemLanguageModel from the Foundation Models framework within a WidgetKit extension to generate a summary of today's activities from my app. The API works as expected when invoked from the widget extension. However, I'm looking for guidance on whether this is a recommended approach in production. Given the execution time and memory constraints of WidgetKit extensions, is it advisable to perform on-device inference directly in the widget? Or is the recommended pattern to generate the summary in the main app (or another process), store the result in an App Group/shared container, and have the widget simply read and display the precomputed output?
0
0
476
Aug ’26
WidgetCenter.getCurrentConfigurations() returns deleted widget configurations after widget resize
Hi everyone, I'm facing an issue with WidgetCenter.shared.getCurrentConfigurations() and I'm trying to determine whether this is expected behavior or a WidgetKit bug. Environment WidgetKit with IntentConfiguration One widget kind: PhotoBoxWidgetGroup Supported families: .systemSmall .systemMedium .systemLarge Steps to reproduce Fresh install the app. Add the PhotoBoxWidgetGroup widget to the Home Screen. Resize the widget between Small, Medium, and Large (or create different sizes during testing). Delete all instances of the widget from the Home Screen. Call: WidgetCenter.shared.getCurrentConfigurations { result in ... } Expected Result Since there are no widgets on the Home Screen, I expect: Widget count: 0 Actual Result getCurrentConfigurations() still returns three configurations: Widget count: 3 Kind: PhotoBoxWidget Family: systemLarge configuration: nil widgetConfigurationIntent: nil Kind: PhotoBoxWidget Family: systemMedium configuration: nil widgetConfigurationIntent: nil Kind: PhotoBoxWidget Family: systemSmall configuration: nil widgetConfigurationIntent: nil Although there are no widgets on the Home Screen, WidgetKit continues to report one configuration for each supported family. Additional observations This does not happen immediately after a fresh install. The issue appears only after the widget has been resized. If I restart the device, getCurrentConfigurations() correctly returns 0. After adding the widget again, resizing it, and deleting it, the issue reappears. I have also tried: reinstalling the app adding confirmation delays before querying querying only when the app becomes active filtering by kind comparing snapshots The result is always the same. Question Has anyone experienced WidgetCenter.shared.getCurrentConfigurations() returning stale widget configurations after widgets have been resized and removed? Is this a known WidgetKit issue, or is there an additional step required to ensure deleted widget configurations are removed from getCurrentConfigurations()? Any guidance or confirmation would be greatly appreciated.
0
0
439
Aug ’26
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
804
Jul ’26
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
87
Activity
2d
Complication flickers in Infograph sub-dials on a single-color Infograph face with Always On (watchOS 27)
On watchOS 27 my app's round complication on the Infograph face disappears for about a second every time I raise or lower my wrist, then comes back. It only happens in the small round dials of that face, only when the face is set to a single color instead of Multicolor, and only when Always On Display is turned on. Everything else on the same watch is fine. my complication placed in a corner of the same face, the same face set to Multicolor, and an Apple complication sitting right next to mine. Other faces set to a single color are fine too, including in their round slots - I tested Modular and Meridian among others. With Always On Display off there is no problem either. What I already checked is: It still happens when my complication is the only one on the face. It still happens when the complication shows just a single line of plain text. The data is not being reloaded. I displayed the timestamp of the entry inside the complication and it does not change across the gap, so the same content is simply being redrawn. Removing the complication and adding it back does not help. Rebuilding with the newest Xcode changes nothing, and an older build behaves exactly the same. The same app, unchanged, worked correctly on watchOS 26. This started right after updating the watch to watchOS 27. Has anyone else run into this on watchOS 27? And has anyone found anything on the app side that makes a difference? I have not found a single thing.
Replies
0
Boosts
0
Views
113
Activity
4d
iOS Dynamically loaded custom fonts in WidgetKit not working on real device (simulator is fine). Sandbox chronod deny file-read-data for font file.
Project structure is: App target + widget extension + widget intent extension All share a common appgroup group.com.x.y and all file handling is done using FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.x.y") so that only the shared container is used. Using the Main app target, a font "Chewy-Regular.ttf" is downloaded and saved to the shared AppGroup container. Font can now be loaded via CTFontManagerRegisterFontsForURL and displayed in a Main App Text view Text("Testing...").font(Font.custom("Chewy-Regular", size: 20)) Now add a Widgetkit widget instance that uses this font. In 'getTimeLine() and getSnapShot() of IntentTimelineProvider we load the font again via CTFontManagerRegisterFontsForURL (this needs to happen again probably because widget runs in a separate process from the main app?). On simulator, the widget will show the correct font. BUT On iPhone7 real device, the widget will show the 'redacted placeholder view'. It seems that something is crashing. I see in the device console : error 14:39:07.567120-0800 chronod No configuration found for configured widget identifier: D9BF75EE-4A04-441A-8C85-1507F7ECE379 fault 14:39:07.625600-0800 widgetxExtension -[EXSwiftUI_Subsystem beginUsing:withBundle:] unexpectedly called multiple times. error 14:39:07.672733-0800 chronod Encountered an error reading the view archive for &amp;lt;private&amp;gt;; error: &amp;lt;private&amp;gt; error 14:39:07.672799-0800 chronod [co.appevolve.onewidget.widgetx:widgetx:small:1536744920620481560@148.0/148.0/20.2] reload: could not decode view error 14:39:07.674984-0800 kernel Sandbox: chronod(2128) deny(1) file-read-metadata /private/var/mobile/Containers/Shared/AppGroup/9B524570-1765-4C24-9E0C-15BC3982F0DC/downloadedFonts/Chewy/Chewy-Regular.ttf error 14:39:07.675762-0800 kernel Sandbox: chronod(2128) deny(1) file-read-data /private/var/mobile/Containers/Shared/AppGroup/9B524570-1765-4C24-9E0C-15BC3982F0DC/downloadedFonts/Chewy/Chewy-Regular.ttf error 14:39:07.708914-0800 chronod [u 8D2C83B3-A6CB-432E-A9D4-9BC8F7056B10:m (null)] [&amp;lt;private&amp;gt;(&amp;lt;private&amp;gt;)] Connection to plugin invalidated while in use. fault 14:39:07.710284-0800 widgetxExtension -[EXSwiftUI_Subsystem beginUsing:withBundle:] unexpectedly called multiple times. error 14:39:07.803468-0800 chronod Encountered an error reading the view archive for &amp;lt;private&amp;gt;; error: &amp;lt;private&amp;gt; It seems that it's a permission issue, and the textview can't access the font file it needs when the widget is rendering. Notes: 1) Font is definitely registered because I can see them in for fontFamily in UIFont.familyNames {             for fontName in UIFont.fontNames(forFamilyName: fontFamily) {                 print(fontName) &amp;amp;#9;&amp;amp;#9;&amp;amp;#9;&amp;amp;#9;&amp;amp;#9;&amp;amp;#9;&amp;amp;#9;&amp;amp;#9;... in both the Main App target and the Widget Extension target 2) If I make make the font part of the app bundle and add to 'Fonts provided by application' , the are loaded absolutely fine in the Main App and the Widget on simulator and iPhone 7 real device. 3) I do see this error sometimes in the Widget extension target log, don't know if it's related. widgetxExtension[1385:254599] [User Defaults] Couldn't read values in CFPrefsPlistSource&amp;lt;0x28375b880&amp;gt; (Domain: group.co.appevolve.onewidget, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd 4) I suspected something to do with app groups, so I tried to copy the font into the Widget Extension container and load from there, but had the same result. Please help! Thank you.
Replies
8
Boosts
1
Views
3.5k
Activity
6d
Semantic Wallet Boarding Pass - Missing airport details ( Gate & terminal) for some airports
Hi team, We've successfully implemented Semantic wallet boarding passes. However, the flight details (gate and terminal) are not appearing for some airports ex: MCT, possibly because this information is not available in Apple’s flight data source. We would like to understand how these details can be kept up to date in Apple’s data source so that they are correctly reflected on the boarding pass. Thank you! Haya
Replies
0
Boosts
0
Views
282
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
1w
watchOS 27 beta: EVERY app update kills WidgetKit complications until the watch is rebooted
Filed as FB24619522 — sysdiagnoses from both devices and the live logs are attached to the report. We ship WidgetKit complications, and on the watchOS 27 betas (24R5360a, paired with iOS 27 24A5430a) they die every time the app gets updated while they're on the active face. Within seconds they turn into empty placeholders and never come back on their own — opening the app, switching faces or reloading timelines from the app does nothing. The watch logs show the extension being killed during the install (normal), and after that watchOS simply can't launch the new copy any more: runningboardd: <OSLaunchdJob | handle=…>: start succeeded, info=spawn failed, error=111: Invalid or missing Program/ProgramArguments chronod(ChronoKit): Reload failed; 0 retries remaining: … "Unknown extension process" Only two things fix it, and both restart chronod: rebooting the watch, or switching the watch language and back (iPhone › Watch app › General › Language & Region, then give it a couple of minutes). Our second extension in the same bundle, which wasn't running during the install, came back fine — so this looks like an OS bug rather than something we can work around in code. iOS 27 widgets seem to have the same problem (this thread, and iPhone in Canada wrote it up on beta 4), and someone posted the identical log lines back in March. FB24619522 — the full story, both sysdiagnoses and the live logs are in the Feedback.
Replies
0
Boosts
3
Views
437
Activity
1w
Live Activity PushType.channel updates silently not delivered on some devices, despite successful activity creation
Hi all, We're seeing an issue where Live Activity content-state push updates sent via PushType.channel(_:) are not consistently delivered to all devices subscribed to the same channel — even though Activity.request() succeeds on every device, and the affected/unaffected devices are both on recent iOS versions well above the 18.1 minimum for channel-based push. Setup: Our backend broadcasts content-state updates to all devices subscribed to a given channel. Activity creation succeeds normally on the affected device, but it never receives a single subsequent update — the activity eventually goes .stale after its staleDate elapses, despite our backend confirming it sent an update to that channel. What we've verified so far: Activity.request() succeeds locally on the affected device, no error thrown. We instrument ContentState's Decodable init(from decoder:) to log every time ActivityKit attempts to decode an incoming push. On the affected device, this log never fires — so no push payload is ever being handed to ActivityKit at all on that device. It's not a decode/payload-format issue. A second device on the identical app build and channel setup receives updates normally in the same window — rules out a backend-wide outage. Both devices are on recent iOS (affected: iPhone 13 Pro Max, iOS 26.5.2 / unaffected: iPhone 15 Pro Max, iOS 26.6) — rules out OS version threshold. No logs, crash reports, or console output of any kind on the affected device around when the update should have arrived — completely silent failure. Question: Has anyone run into a device silently failing to receive PushType.channel broadcast updates like this? Are there known conditions (notification permissions, Low Power Mode, Background App Refresh, channel subscription expiry/limits, etc.) that could cause this? Is there any client-side API to check the health/status of a device's channel subscription, to distinguish "not subscribed," "subscription expired," and "subscribed but delivery failed"? Any pointers appreciated — happy to share more details if useful.
Replies
0
Boosts
0
Views
326
Activity
2w
WidgetKit timeline crashes with EXC_RESOURCE (memory limit=30MB) when generating entries from a large photo album
Environment: Xcode 15/16, iOS 17/18, WidgetKit (IntentTimelineProvider) Issue: I have a photo widget that lets users pick an album and rotate through its photos on a timer (configurable refresh interval). When the selected album is large, the widget extension is Jetsam-killed with: Thread X: EXC_RESOURCE (RESOURCE_TYPE_MEMORY: high watermark memory limit exceeded) (limit=30 MB) After this happens, the widget stops refreshing entirely and stays on a stale/placeholder image until the app is relaunched. What I've tried: Downsampling with CGImageSourceCreateThumbnailAtIndex + kCGImageSourceThumbnailMaxPixelSize before building entries Reducing entry count and using policy .after(nextDate) instead of pre-building a full day of entries Still seeing intermittent Jetsams on albums with several hundred photos Questions: Is there a recommended max total archived timeline size WidgetKit expects developers to stay under, beyond "keep it small"? For a "large photo album" use case specifically, is the recommended pattern to pre-generate and cache small thumbnails in the App Group container ahead of time, rather than downsampling on demand inside getTimeline()? Is there guidance on how many timeline entries is "too many" before WidgetKit itself starts struggling to archive/deliver them, independent of image size? useful than a forum thread — let me know what info would help most.
Replies
0
Boosts
0
Views
228
Activity
3w
Widget is crashing with 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=30 MB, unused=0x0)
I have created widget which supports medium and large family similar to news feed app like title and image by configuring the medium widget with 2 articles and large with 4 articles where each article has title and it's image with size 46x46 and 61x61. When am adding the small and large widgets to my Home Screen getting memory limit (Thread 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=30 MB, unused=0x0)(crash and the widget is not refreshing and some times widgets is showing the skeletons instead of data. This is my timeline provider     func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) {             widgetVM.getRecommendedDataForWidget{ (result) in                 switch result {                 case .success(let items):                     let entries =  getRecommendedWidgetTimeLineEntries(recFeedModel: items)                     let timeline = Timeline(entries: entries, policy: .atEnd)                     completion(timeline)                 case .failure(_):                         let entry = RecommendedWidgetEntry(date: Date(), recommedationData: WidgetFeedModel.getPlaceholderData())                         let timeline = Timeline(entries: [entry], policy: .never)                         completion(timeline)                 }             }         }         else {             if accessTokenValue == nil { // if token is nil then considering it as member is not logged in.                 let entry = RecommendedWidgetEntry(date: Date(), recommedationData: [])                 let timeline = Timeline(entries: [entry], policy: .never)                 completion(timeline)                 return             }     } Could you please help me out on this as this is priority for me as part of app release. I couldn't find out the reason for this. Thanks
Replies
10
Boosts
0
Views
4.4k
Activity
3w
AlarmKit Bug: Dismissing the alarm by touching the bottom notch area.
This is about AlarmKit, and this problem is also happening with the native phone alarm. I’m working on some alarm apps, and some users have been complaining that when they get their phone, the alarm is being dismissed. We were never able to simulate this until today. We noticed that when touching the bottom notch of the phone, below the stop swipe area, sometimes the alarm is simply dismissed. In some cases, you can see the same UI repeated behind the screen; other times, you can’t drag, but it also dismisses the alarm. This seems to have been happening for quite a while with our users. They grab their phones, unintentionally touch that area, and dismiss the alarm. It’s very critical for us because we present other buttons on AlarmKit for the user to click on (guess which bird is singing, for example). Feedback Ticket Created: FB24407814
Replies
1
Boosts
0
Views
520
Activity
3w
Custom icons or background imagery for App Shortcut tiles in the Shortcuts app?
Hi — I’m trying to understand what customization is currently supported for App Shortcuts as they appear inside the Shortcuts app. From the public App Intents APIs, it looks like an AppShortcut can specify a systemImageName, and an AppShortcutsProvider can specify a shortcutTileColor. I haven’t been able to find documentation for either of the following: Using a custom app-provided icon/image asset instead of an SF Symbol Using custom imagery or a background image for the App Shortcut tile itself However, some Apple apps such as Music and Podcasts appear to use richer/custom artwork in their Shortcuts tiles, which made me wonder whether there is a supported API or approach that I’m missing. Are custom icons or background images currently supported for App Shortcut tiles through public APIs? If not, are the richer treatments used by Apple Music/Podcasts based on system-only capabilities that aren’t currently available to third-party apps? Thanks!
Replies
0
Boosts
0
Views
247
Activity
4w
iCloud无法使用
在iOS27测试版回退到iOS26正式版后iCloud无法备份、恢复照片,求解决方案
Replies
0
Boosts
0
Views
196
Activity
4w
Widget Extension still uses system language even though CFBundleAllowMixedLocalizations = NO is set
I have an app with a Widget Extension. Both the main app and the widget extension link against the same Swift Package, which contains a localization bundle (String Catalog) used by SwiftUI views inside the package. To make the package's views follow the app's configured language (rather than the system language), I set CFBundleAllowMixedLocalizations to NO in the Info.plist of each target (main app and widget extension). Behavior in the main app: This works as expected. If the app only supports Korean, the package's views display Korean text even when the system language is set to English. Behavior in the widget: The same views (from the same package) display English instead of Korean, even though the widget extension has the identical CFBundleAllowMixedLocalizations = NO setting and the widget's view code lives entirely in the package — not in the widget extension target itself. Question: As far as I understand, widgets are supposed to follow the host app's language setting. Given that both targets have the same Info.plist configuration, why would the widget extension resolve localized strings differently from the main app for code in the same package? Is this expected behavior for widget extensions specifically, or a bug? Is there a recommended workaround to force a widget extension (and by extension, the Swift Package code it runs) to use the app's language instead of the system language?
Replies
1
Boosts
0
Views
946
Activity
Aug ’26
On vision 27, accessoryRectangular shows blank
Hi, On visionOS 27 simulator accessoryRectangular widget shows completely blank with no text. The same widget shows up correctly on iOS 27 simulator. What I have tried: I have checked the timeline provider and they all seem to be generating timeline entries. supportedFamilies include accessoryRectangular I have even hard coded the content in the view for the widget yet only accessoryRectangular for visionOS 27 shows up blank. Isolated problem The same widget shows up correctly on iOS 27 simulator. The problem is only with visionOS 27. Environment: macOS: 26.6.1 (25G76) Xcode: 27.0 beta 5 (27A5237l) Simulator: visionOS 27.0 Questions What am I missing? How can I resolve it? Is this a known issue? Has anyone gotten accessoryRectangular widget showing up on visionOS 27 simulator? Any help on this would be much appreciated.
Replies
0
Boosts
0
Views
473
Activity
Aug ’26
I thought you kindly deleted the account
So how can I still login
Replies
0
Boosts
0
Views
272
Activity
Aug ’26
Is it recommended to use Foundation Model's SystemLanguageModel directly in a WidgetKit extension?
I'm exploring the possibility of using Apple's SystemLanguageModel from the Foundation Models framework within a WidgetKit extension to generate a summary of today's activities from my app. The API works as expected when invoked from the widget extension. However, I'm looking for guidance on whether this is a recommended approach in production. Given the execution time and memory constraints of WidgetKit extensions, is it advisable to perform on-device inference directly in the widget? Or is the recommended pattern to generate the summary in the main app (or another process), store the result in an App Group/shared container, and have the widget simply read and display the precomputed output?
Replies
0
Boosts
0
Views
476
Activity
Aug ’26
Is there a way to know when widget is installed/uninstalled?
Hello, For tracking purpose, is there a way to know when a widget is installed/uninstalled? Also, would it be possible to check which size widget was installed?
Replies
10
Boosts
1
Views
7.0k
Activity
Aug ’26
WidgetCenter.getCurrentConfigurations() returns deleted widget configurations after widget resize
Hi everyone, I'm facing an issue with WidgetCenter.shared.getCurrentConfigurations() and I'm trying to determine whether this is expected behavior or a WidgetKit bug. Environment WidgetKit with IntentConfiguration One widget kind: PhotoBoxWidgetGroup Supported families: .systemSmall .systemMedium .systemLarge Steps to reproduce Fresh install the app. Add the PhotoBoxWidgetGroup widget to the Home Screen. Resize the widget between Small, Medium, and Large (or create different sizes during testing). Delete all instances of the widget from the Home Screen. Call: WidgetCenter.shared.getCurrentConfigurations { result in ... } Expected Result Since there are no widgets on the Home Screen, I expect: Widget count: 0 Actual Result getCurrentConfigurations() still returns three configurations: Widget count: 3 Kind: PhotoBoxWidget Family: systemLarge configuration: nil widgetConfigurationIntent: nil Kind: PhotoBoxWidget Family: systemMedium configuration: nil widgetConfigurationIntent: nil Kind: PhotoBoxWidget Family: systemSmall configuration: nil widgetConfigurationIntent: nil Although there are no widgets on the Home Screen, WidgetKit continues to report one configuration for each supported family. Additional observations This does not happen immediately after a fresh install. The issue appears only after the widget has been resized. If I restart the device, getCurrentConfigurations() correctly returns 0. After adding the widget again, resizing it, and deleting it, the issue reappears. I have also tried: reinstalling the app adding confirmation delays before querying querying only when the app becomes active filtering by kind comparing snapshots The result is always the same. Question Has anyone experienced WidgetCenter.shared.getCurrentConfigurations() returning stale widget configurations after widgets have been resized and removed? Is this a known WidgetKit issue, or is there an additional step required to ensure deleted widget configurations are removed from getCurrentConfigurations()? Any guidance or confirmation would be greatly appreciated.
Replies
0
Boosts
0
Views
439
Activity
Aug ’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
554
Activity
Jul ’26
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
804
Activity
Jul ’26