WidgetKit

RSS for tag

Show relevant, glanceable content from your app on iOS and iPadOS Home Screen and Lock Screen, macOS Desktop, Apple Watch Smart Stack and Complications, and in StandBy mode on iPhone.

WidgetKit Documentation

Posts under WidgetKit tag

311 Posts
Sort by:
Post not yet marked as solved
0 Replies
68 Views
My app has two static widgets. In the widget extension, I have the following code: import WidgetKit import SwiftUI import ItemWidgetsKit @main struct ItemWidgetsBundle: WidgetBundle { var body: some Widget { RecentSavesWidget() RecommendationsWidget() } } the rest of the code, including the two Widget implementations, the TimelineProvider, etc, are in the imported ItemsWidgetKit, which is a library inside a Swift Package containing several libraries. These two widgets work as expected. Now I am adding a configurable widget, and the code above changes like so: import WidgetKit import SwiftUI import ItemWidgetsKit @main struct ItemWidgetsBundle: WidgetBundle { @WidgetBundleBuilder var body: some Widget { makeWidgets() } func makeWidgets() -> some Widget { if #available(iOS 17.0, *) { return WidgetBundleBuilder.buildBlock(RecentSavesWidget(), TopicRecommendationsWidget()) } else { return WidgetBundleBuilder.buildBlock(RecentSavesWidget(), RecommendationsWidget()) } } } TopicRecommendationsWidget is similar to RecommendationsWidget except that it lets you choose a topic to display recommendations for, by long pressing and selecting an intent. I followed the same approach of the other two widgets, and put the code inside ItemWidgetsKit This time, though, the widget does not work, and it only loads the placeholder; in fact, in the AppIntentTimelineProvider implementation (see below) only placeholder(in:) gets ever called @available(iOS 17.0, *) public struct TopicTimelineProvider: AppIntentTimelineProvider { public func placeholder(in context: Context) -> TopicEntry { return TopicEntry(date: Date(), content: TopicContent.sampleContent) } public func snapshot(for configuration: TopicIntent, in context: Context) async -> TopicEntry { return TopicEntry(date: Date(), content: configuration.topicEntity.topic) } public func timeline(for configuration: TopicIntent, in context: Context) async -> Timeline<TopicEntry> { let entry = TopicEntry(date: Date(), content: configuration.topicEntity.topic) return Timeline(entries: [entry], policy: .never) } } for more context, here's the code for the configurable Widget implementation (that resides inside ItemWidgetsKit @available(iOS 17.0, *) public struct TopicRecommendationsWidget: Widget { let kind: String public init() { self.kind = WidgetKind.topicRecommendations // a string stored elsewhere } public var body: some WidgetConfiguration { AppIntentConfiguration(kind: kind, intent: TopicIntent.self, provider: TopicTimelineProvider()) { entry in TopicWidgetContainerView(entry: entry) } .configurationDisplayName("New Recommendations") .description("Select a Topic") .supportedFamilies([.systemMedium, .systemLarge]) } } Any Idea why this happens and what would be the solution to this problem? Thank you
Posted
by GioR.
Last updated
.
Post not yet marked as solved
1 Replies
288 Views
TLDR; Can I have a widget without a Timeline? My previous watch app had a complication. Simply so it can be added to the watch face for a quick launch of the app. However now seeing that method is deprecated in favour of widgets. Can I add a widget without the need for all the Timeline as all I want is a button on the watch face to launch into my app. No data is updated over time so no need for all the extra timeline code.
Posted
by RyanTCB.
Last updated
.
Post not yet marked as solved
2 Replies
1.1k Views
Before iOS 16.1 my app was woking good, if the user set the app language to other language than his device language, my app, widget + extensions all use this language... After iOS 16.1 if user set the app language to other language than his device language, my app works with this language but the widget + extensions works with the device language, not my app language... For Example:     @Environment(\.locale.languageCode) private var userLocal before iOS 16.1 userLocal would be the app local, after iOS 16.1 it return the device local Any idea why Apple did that? is this a bug? How to set the widget language to match my app language now? even set .environment(\.locale, dose not work when use Strings(table: because it's still get the bundle that match device language.
Posted
by iTarek.
Last updated
.
Post not yet marked as solved
0 Replies
100 Views
I'm building complications using WidgetKit and SwiftUI. The complications work, but the previews don't appear right away when applying the .watchface. How can I ensure the complication previews show up immediately when a user adds the watch face? Any guidance is appreciated.
Posted Last updated
.
Post not yet marked as solved
5 Replies
346 Views
My background audio app stops updating its Live Activity after the iPhone locks, and doesn't resume updating the activity after tapping the screen or even after FaceID unlocks the device (without opening the lock screen). My live activity requests a ContentState update & iOS updates the content for the activity as below: Task{ log.debug("LiveActivityManager.updateLiveActivity() with new ContentState") await liveActivity.update( ActivityContent(state:contentState, staleDate:nil) ) } Below what my log looks like: <<<<SWIPE LOCK SCREEN DOWN>>>> DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState iOS: Updating content for activity 0A519263-1E46-4BB6-BA4F-F3DDBC081AB4 DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState iOS: Updating content for activity 0A519263-1E46-4BB6-BA4F-F3DDBC081AB4 <<<<PRESS LOCK BUTTON->Lock iPhone>>>> INFO: --------protectedDataWillBecomeUnavailableNotification-------- DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState iOS: Updating content for activity 0A519263-1E46-4BB6-BA4F-F3DDBC081AB4 DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState <<<<LOOK AT & TAP LOCK SCREEN->Unlock iPhone without swiping up>>>> INFO: --------protectedDataDidBecomeAvailableNotification----------- DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState DEBUG: LiveActivityManager.updateLiveActivity() with new ContentState As shown in the log, normally iOS updates the content for my activity after my liveActivity.update request. This works fine in the Dynamic Island and when after switching apps and swiping down to see the lock screen without locking the phone. However, once I lock the phone, iOS stops updating the Live Activity content, and doesn't resume updates until after the app regains the foreground at least once. Has anyone else encountered this behavior? Is this a setting that I'm missing, or a bug?
Posted
by zabelc.
Last updated
.
Post not yet marked as solved
2 Replies
438 Views
I'll preface this to say that I'm not 100% sure this is all accurate, but I wanted to share this problem I was seeing developing a widget for a SwiftUI app in case it helps someone else get to a solution faster. Two weeks ago I released a version of an app which contained a brand new widget. For the kind property of the widget's configuration I just used something generic: AppWidget. Last week we wanted to add an additional widget into the app and I realized that I ought to make the kind be a little more specific. So I renamed the first kind from AppWidget to DailyPromptWidget ... and made the second widget use a kind named DailyCheckInWidget. Then, we started seeing issues where the widget wasn't responding to taps and would eventually go blank. I could add in a new widget to the home screen and that'd work fine. Searching the Internet for ideas yielded nothing. I connected my iPhone to my Mac and launched the Console app and then started tapping on the non-responsive widget. I discovered a few output messages like this: Timeline[my.bundle.id::my.bundle.id.widgetid:AppWidget:systemMedium::338.00/158.00/21.60:(null)]--CD0C49416486::0xc46382000) Unable to create CHUISWidgetLaunchRequest without a effectiveContainerBundleIdentifier I was able to reproduce the issue by renaming the bundle ID of the widget (and leaving the working widget on the home screen). Tapping it gave the same exact error. Another error, which clued me in more: Content load failed: unable to find or unarchive file for key: [my.bundle.id.widgetid:AppWidget:systemMedium::338.00/158.00/21.60:(null)] on no host. The session may still produce one shortly. Error: Using url `file:///private/var/mobile/Containers/Data/PluginKitPlugin/012DB9D2-07F7-4383-9CCE-B040652B7999/SystemData/com.apple.chrono/placeholders/AppWidget/systemMedium----338.00w--158.00h--21.60r--0f--0.00t-0.00l-0.00b0.00t.chrono-timeline` ... Error Domain=NSCocoaErrorDomain Code=4 "The file "systemMedium----338.00w--158.00h--21.60r--0f--0.00t-0.00l-0.00b0.00t.chrono-timeline" doesn't exist." UserInfo={NSFilePath=/private/var/mobile/Containers/Data/PluginKitPlugin/012DB9D2-07F7-4383-9CCE-B040652B7999/SystemData/com.apple.chrono/placeholders/AppWidget/systemMedium----338.00w--158.00h--21.60r--0f--0.00t-0.00l-0.00b0.00t.chrono-timeline, NSUnderlyingError=0x3025a1d10 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}} So, I tried finding those files in the simulator data on my Mac. Inside the placeholders/ directory are directories with the names of all the widget kind I had used (the old and the new). Inside those named kind directories are, what look to be, files representing each timeline entry. It appears that if you change the kind string in your widget's configuration, the widget you've added to your home screen does not get updated and will continue looking for the old timeline entry files in the original kind directory. The solution? Either don't rename the kind once you've released it on the App Store, or instruct customers to remove the widget and add it back after they've installed your app update. It'd be nice if an app update would also update the kind directory name.
Posted Last updated
.
Post not yet marked as solved
1 Replies
288 Views
iOS app with Home Screen and Lock Screen widgets written in Swift/SwiftUI. I've never been able to get widgets to work properly. It's more pronounced on Lock Screen widgets, so let's try that method first... The app stores data in Core Data as an Event. They're read into my model and stored as WidgetEventDetails structs: struct WidgetEventDetails: AppEntity, Identifiable, Hashable { public var eventId: String public var name: String public var date: Date public var id: String { eventId } This all works absolutely fine in the iOS app, and each one is unique based on the eventId. When I go to add a Lock Screen widget, I customise the Lock Screen, tap in the section to add a widget, and my widgets appear correctly and are selectable: (bottom right, says "1y 28w 1d") So, I tap it and it appears in the widgets section: But it appears as "17w 6d", which is a different event entirely. Notice how the one in the selectable widgets has changed to "15w 5d", and the one I tapped (1y 28w 1d) is nowhere to be seen. So, I tap the one in the top row (17w 6d) to select an event, and this appears, suggesting that the event is the "Edinburgh & Glasgow 2024-02" event: But that event is actually only a day away (1d), so that's not the one I selected at all. I tap the list and see these events: I select "Las Vegas 2024", which is 17w 3d away, and this is shown: 17w 6d is a different event, not Las Vegas 2024. So, I tap it again and see this. The "Loading" text appears for ages, but occasionally does show the full list, as before: I select "Edinburgh & Glasgow 2024-02" which is 1d away, and I see this again: So, I resign myself to hoping it'll just figure itself out, and I tap "Done": "17w 6d" again :( I finish customising, and exit the customisation screen. I show the Lock Screen, and I see this: Why doesn't this work? Here's the code: @main struct WidgetExtensionBundle: WidgetBundle { @WidgetBundleBuilder var body: some Widget { WidgetExtension() } } struct WidgetExtension: Widget { var body: some WidgetConfiguration { AppIntentConfiguration(kind: kWidgetKind, intent: WidgetEventIntent.self, provider: WidgetEventTimelineProvider()) { entry in WidgetEntry(entry: entry) .environment(modelData) } .configurationDisplayName(NSLocalizedString("AddingWidget_Title", comment: "Adding the Widget")) .description(NSLocalizedString("AddingWidget_Description", comment: "Adding the Widget")) .supportedFamilies([.accessoryCircular, .accessoryInline, .accessoryRectangular, .systemSmall, .systemMedium]) .contentMarginsDisabled() } } struct WidgetEventIntent: WidgetConfigurationIntent { static let title: LocalizedStringResource = "AddingWidget_Title" static let description = IntentDescription(LocalizedStringResource("AddingWidget_Description")) @Parameter(title: LocalizedStringResource("Event")) var event: WidgetEventDetails? init(event: WidgetEventDetails? = nil) { self.event = event } init() {} static var parameterSummary: some ParameterSummary { Summary { \.$event } } } struct EventQuery: EntityQuery, Sendable { func entities(for identifiers: [WidgetEventDetails.ID]) async throws -> [WidgetEventDetails] { modelData.availableEvents.filter { identifiers.contains($0.id) } // availableEvents is just [WidgetEventDetails] } func suggestedEntities() async throws -> [WidgetEventDetails] { return modelData.availableEvents.filter { $0.type == kEventTypeStandard } } } If you think it's the TimelineProvider causing it, I can provide that code, too.
Posted
by darkpaw.
Last updated
.
Post not yet marked as solved
11 Replies
6.8k Views
Any insights on how to incorporate CloudKit (or CoreData) in the WidgetKit extension? Where in the WidgetKit api do I make the asynchronous call to load the data to be available for the TimelineProvider?
Posted
by cristosv.
Last updated
.
Post not yet marked as solved
1 Replies
225 Views
We use a local swift package in 6 of our app extensions. The product from the local package that we link to each app extension is a dynamic framework. And while the dynamic framework is copied into the final app bundle once, the resource bundles of each target that comprise the dynamic framework is copied into each app extension. I'd much rather have the bundles be copied into the dynamic framework once to prevent app bloat. Here is a visualization of the issue: . └── MyApp.ipa/ ├── MyApp (executable) ├── MyDynamicFramework_TargetA.bundle ├── MyDynamicFramework_TargetB.bundle ├── MyDynamicFramework_TargetC.bundle ├── Frameworks/ │ └── MyDynamicFramework.framework/ │ ├── TargetA │ ├── TargetB │ └── TargetC └── PlugIns/ ├── Widgets.appex/ │ ├── MyDynamicFramework_TargetA.bundle │ ├── MyDynamicFramework_TargetB.bundle │ └── MyDynamicFramework_TargetC.bundle ├── Intents.appex/ │ ├── MyDynamicFramework_TargetA.bundle │ ├── MyDynamicFramework_TargetB.bundle │ └── MyDynamicFramework_TargetC.bundle ├── IntentsUI.appex/ │ ├── MyDynamicFramework_TargetA.bundle │ ├── MyDynamicFramework_TargetB.bundle │ └── MyDynamicFramework_TargetC.bundle ├── NotificationContent.appex/ │ ├── MyDynamicFramework_TargetA.bundle │ ├── MyDynamicFramework_TargetB.bundle │ └── MyDynamicFramework_TargetC.bundle ├── RichPushContent.appex/ │ ├── MyDynamicFramework_TargetA.bundle │ ├── MyDynamicFramework_TargetB.bundle │ └── MyDynamicFramework_TargetC.bundle └── NotificationService.appex/ ├── MyDynamicFramework_TargetA.bundle ├── MyDynamicFramework_TargetB.bundle └── MyDynamicFramework_TargetC.bundle Notice that the resource bundles of Target A, B, and C are copied multiple times causing an unhealthy app size. I'd either like the resource bundles to be copied into MyDynamicFramework or copied once into the app bundle and let the app extensions reference them. Given the SPM + Xcode linking is a black box for the most part, how would I accomplish this?
Posted Last updated
.
Post not yet marked as solved
2 Replies
343 Views
iPhone 16.0 16.0.2 系统上运行小组件出现问题, 其他系统没有问题 SendProcessControlEvent:toPid: encountered an error: Error Domain=com.apple.dt.deviceprocesscontrolservice Code=8 "Failed to show Widget 'com.jiduauto.iphone.jdcomiphoneWidget' error: Error Domain=FBSOpenApplicationServiceErrorDomain Code=5 "The request to open "com.apple.springboard" failed." UserInfo={NSLocalizedDescription=The request to open "com.apple.springboard" failed., NSLocalizedFailureReason=Unexpected error type., NSUnderlyingError=0x600002bbd7a0 {Error Domain=BSServiceConnectionErrorDomain Code=3 "XPC error received on message reply handler" UserInfo={BSErrorCodeDescription=OperationFailed, NSLocalizedFailureReason=XPC error received on message reply handler}}, BSErrorCodeDescription=InvalidResponse}." UserInfo={NSLocalizedDescription=Failed to show Widget 'com.jiduauto.iphone.jdcomiphoneWidget' error: Error Domain=FBSOpenApplicationServiceErrorDomain Code=5 "The request to open "com.apple.springboard" failed." UserInfo={NSLocalizedDescription=The request to open "com.apple.springboard" failed., NSLocalizedFailureReason=Unexpected error type., NSUnderlyingError=0x600002bbd7a0 {Error Domain=BSServiceConnectionErrorDomain Code=3 "XPC error received on message reply handler" UserInfo={BSErrorCodeDescription=OperationFailed, NSLocalizedFailureReason=XPC error received on message reply handler}}, BSErrorCodeDescription=InvalidResponse}., NSUnderlyingError=0x600002bbd5f0 {Error Domain=FBSOpenApplicationServiceErrorDomain Code=5 "The request to open "com.apple.springboard" failed." UserInfo={NSLocalizedDescription=The request to open "com.apple.springboard" failed., NSLocalizedFailureReason=Unexpected error type., NSUnderlyingError=0x600002bbd7a0 {Error Domain=BSServiceConnectionErrorDomain Code=3 "XPC error received on message reply handler" UserInfo={BSErrorCodeDescription=OperationFailed, NSLocalizedFailureReason=XPC error received on message reply handler}}, BSErrorCodeDescription=InvalidResponse}}} Domain: DTXMessage Code: 1 User Info: { DVTErrorCreationDateKey = "2024-02-19 08:02:14 +0000"; } System Information macOS Version 13.5.2 (Build 22G91) Xcode 15.0 (22265) (Build 15A240d) Timestamp: 2024-02-19T16:02:14+08:00
Posted
by yuantan.
Last updated
.
Post not yet marked as solved
0 Replies
142 Views
I'm stuck fetching location inside iOS app's widget extension running on MacOS. locationManager.authorizationStatus == .notDetermined always returns true, meanwhile main app, running on MacOS has permission for location in MacOS system settings and doesn't have any problems with using geodata. Is it possible to fetch a location inside of iOS app's widget extension running on MacOS and if yes, what could I be doing wrong?
Posted
by stepanick.
Last updated
.
Post marked as Apple Recommended
1.8k Views
Hi guys, I am migrating my widgets to iOS 17 and because I already manage my layout margins, I just want to disable to new built-in widget content margins. I did it by using ".contentMarginsDisabled()" on the WidgetConfiguration and it works fine at run time. WIDGET CODE struct MyWidget: Widget { let kind: String = "MyWidget" var body: some WidgetConfiguration { return IntentConfiguration(kind: kind, intent: MyWidgetIntent.self, provider: WidgetProvider<MyWidgetIntent>()) { entry in WidgetView<MyWidgetIntent>(entry: entry) } .configurationDisplayName("My Widget") .supportedFamilies([WidgetFamily.systemMedium]) .contentMarginsDisabled() // <-- HERE } } RESULT Nevertheless, when previewing the WidgetView in a WidgetPreviewContext I didn't find anyway to disable the content margins (because manipulating directly the view and not a WidgetConfiguration). PREVIEW CODE struct MyWidget_Previews: PreviewProvider { static var previews: some View { WidgetView<MyWidgetIntent>(entry: WidgetEntry<MyWidgetIntent>()) // .padding(-16) Need to add this negative padding to disable margin .previewContext( WidgetPreviewContext(family: .systemMedium)) } } Do you know how to disable the content margins for widget preview?
Posted
by Clem23.
Last updated
.
Post not yet marked as solved
1 Replies
505 Views
Hey there, I'm implementing Watch Complications in an existing project, and I'm having the problem that transferCurrentComplicationUserInfo(_:) works exactly as transferUserInfo(_:) is described in the documentation, but not as it should. That is, when the WatchApp is opened, func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) receives the data sent by transferCurrentComplicationUserInfo(_:). If not, the data is queued until the Watch App is opened again. In other words, transferCurrentComplicationUserInfo(_:) never wakes up the ExtensionDelegate when the Watch App is not running. Has anyone experienced the same thing and know how to fix it? More details: Testing on iPhone 11 (iOS 17.1.2) and Apple Watch SE (WatchOS 10.2) I made sure that the quota of 50 is not exhausted when I test. The WatchApp is still dual-target (I want to avoid having to migrate to single-target and SwiftUI lifecycle) Watch App code: class ExtensionDelegate: NSObject, WKExtensionDelegate, WCSessionDelegate { let session = WCSession.default override init() { super.init() if WCSession.isSupported() { session.delegate = self session.activate() } } func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) { WatchWidgetSessionHandler.shared.processComplicationUserInfo(userInfo) } } IOS App code: class WatchAppDataManager: NSObject, WCSessionDelegate { override init() { super.init() let session = WCSession.default session.delegate = self session.activate() } func sendDataToWidget(for kinds: [WatchWidgetKind]) async { guard WCSession.default.activationState == .activated, WCSession.default.isComplicationEnabled else { return } let widgetsData = dataProvider.getData(for: kinds) if !widgetsData.isEmpty { WCSession.default.transferCurrentComplicationUserInfo(widgetsData) } } }
Posted Last updated
.
Post marked as solved
15 Replies
5.1k Views
I am playing around with Live Activities and got everything working on the iOS 16.1 beta 2 simulator using Xcode 14.1 beta 2 (14B5024i). However, running the same code on a real physical device (iPhone X) running iOS 16.1 beta 2 does not show the Live Activity on the lock screen at all. 😵 Did anyone get their Live Activity working on a real device yet, or is this an issue with the current beta? Things I have already checked: ActivityAuthorizationInfo().areActivitiesEnabled returns true on my physical device let activity = try Activity.request(...) successfully completes without throwing and I can see the activity.id printed to the console Other live activities - such as the iOS system timer activity - do show up on my physical device just fine
Posted
by aschuch.
Last updated
.
Post not yet marked as solved
3 Replies
285 Views
Hi all, I am trying to create a widget for my app but I cannot use the Preview feature of Xcode. Xcode enters a build loop and builds the project over and over. There is no error or message. There is only a loading spinner and lots of build. It doesn't matter how much time I wait, it never finishes. I tried to clean the build folder, delete all preview simulators, quit, and reopen the XCode but nothing helped.
Posted Last updated
.
Post not yet marked as solved
2 Replies
2.3k Views
After updating our app some of our users are seeing that their widget has gone blank, the whole widget it just white. The only way to make the widget render again is to reboot the phone. This seems to be happening randomly and mainly on iOS17. Looking on the web, seems like other people are also having this issue so hopefully Apple will make a fix at some point but I'm wondering if other people have had this issue and figured out a workaround to stop it happening? Thanks.
Posted
by markdaws.
Last updated
.
Post not yet marked as solved
5 Replies
1.4k Views
Following article Creating a widget extension on developer.apple.com (https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension) I encountered a problem with XCode preview: it shows an error with message | RemoteHumanReadableError: Failed to launch agent | No plugin is registered to launch the process type widgetExtension. Can someone help me? macOS 13.4 XCode 14.3.1
Posted
by Ratka6.
Last updated
.
Post not yet marked as solved
1 Replies
257 Views
Hello all, I'm facing a major bug where all my app's Interactive Widgets stopped working on iOS 17.4 - testing on multi devices and iOS simulators. App Intent + SwiftData. Stopped working totally. Any advice?! Thanks a lot.
Posted
by DudiSG.
Last updated
.
Post not yet marked as solved
1 Replies
197 Views
When I upgraded the system to iOS 17.4 Beta, the AppEnum in my code became invalid. I selected an AppEnum option on the desktop widget, but the widget did not synchronize.
Posted
by Joelala.
Last updated
.