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
70 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
Post not yet marked as solved
0 Replies
110 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
by
Post not yet marked as solved
1 Replies
226 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
by
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
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
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
by
Post not yet marked as solved
5 Replies
356 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
Post not yet marked as solved
0 Replies
185 Views
Hey I try to post my issue here but keep getting a sensitive problem, so I posted on stack overflow (See here), but really appreciate your help on any forum. The post is about an issue with the auto refresh of the widget and the same behaviour when refreshing from a button in the widget (Done with AppIntent).
Posted
by
Post not yet marked as solved
0 Replies
265 Views
Hi all, I am experimenting with Widgets and I would like to add to my SwiftUI app a Widget that can be run on iOS 14. My Mac has macOS Sonoma 14.4, I am using Xcode 15.3. My SwiftUI app can target back to iOS 14. When adding a Widget with Xcode 15.3, the Widget can only target iOS 17. If I downgrade the minimum iOS version of the Widget extension, then my project doesn't compile anymore. I have tried multiple attempts to solve this problem. All of them have failed. If would be nice if someone could give me help on one or more of them: I have tried to install Xcode version 12.5.1, but apparently it is not possible on Sonoma. (It gets installed, but then I get an error on the first execution) I have tried to install a virtual machine in Parallels with macOS Big Sur, but I wasn't able to find the IPSW installation file from the Apple developer downloads. I have created a widget with Xcode 15.3, then replaced the files with the content of a new widget found in a YouTube video, and modified the project.pbxproj inside the xcodeproj as in the attached file (essentially I have added WidgetKit as a framework with an older version, that doesn't require iOS 17) Now: the full app compiles I can test the widget in the Xcode preview I can't deploy the app on both my iPhone with iOS 17.4, and on a Simulator with iOS 15. As I am not expert, probably I miss many steps or I have done many errors. Can anyone please help me in adding an iOS 14 Widget on Xcode 15.3 on Sonoma?
Posted
by
Post not yet marked as solved
0 Replies
172 Views
Hello, When an app is updated, if a widget was set to show in standby (smart rotate / suggestions turned off), it is removed and must be re-added. This seems to be a really bad UX. Is there a way to to prevent this, or is it an iOS bug? Noticed on 17.3 / 17.4 Thanks
Posted
by
Post not yet marked as solved
0 Replies
209 Views
I have an iOS app with widgetkit extension, and the widgets stopped updating. I attached the console, and saw these lines for widgets of my app: com.apple.widget.myApp::myWidgetKind::-6207022974507159915:417E34:[ {name: Widget Refresh Policy, policyWeight: 0.010, response: {Decision: Must Not Proceed, Score: 0.00, Rationale: [{onOverrideList == 1 AND IndividualBalance == -1}]}} ], FinalDecision: Must Not Proceed} The IndividualBalance == -1 apparently means that the app was updating widgets too often, but what about onOverrideList == 1? There seems to be no info online about this flag, and LLMs seem to suggest that the app got onto some kind of Apple's blacklist for updating too often, is that right?
Posted
by
Post not yet marked as solved
0 Replies
119 Views
Widgets are activated by the iOS system at regular intervals, and the task code defined in the TimelineProvider is executed. How long can this task code be executed at most? I don't think the system will allow tasks defined in the timeline to be executed continuously (looking like a background resident program), so there must be a time limit. If you know, or if there are related document links, please let me know Thank you.
Posted
by
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
Post not yet marked as solved
2 Replies
217 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
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
Post not yet marked as solved
0 Replies
262 Views
I am working on a radio app. This is the first time and I have a problem with lock Screen Audio Card. According to docs It looks ok but could you please check why I can not display Audio Now Playing Card on lock Screen. 2 Code samples, 1. Now Playing and 2. Logic of current song and Album art. 1. Now Playing // Create a dictionary to hold the now playing information var nowPlayingInfo: [String: Any] = [:] // Set the title of the current song nowPlayingInfo[MPMediaItemPropertyTitle] = currentSong // If album art URL is available, fetch the image asynchronously if let albumArtUrl = albumArtUrl { URLSession.shared.dataTask(with: albumArtUrl) { data, _, error in if let data = data, let image = UIImage(data: data) { // Create artwork object let artwork = MPMediaItemArtwork(boundsSize: image.size) { _ in image } // Update now playing info with artwork on the main queue DispatchQueue.main.async { nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo } } else { // If there's an error fetching the album art, set now playing info without artwork MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo print("Error retrieving album art data:", error?.localizedDescription ?? "Unknown error") } }.resume() } else { // If album art URL is not available, set now playing info without artwork MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo } } 2. Current Song, Album Art Logic let parts = currentSong.split(separator: "-", maxSplits: 1, omittingEmptySubsequences: true).map { $0.trimmingCharacters(in: .whitespaces) } let titleWithExtra = parts.count > 1 ? parts[1] : "" let title = titleWithExtra.components(separatedBy: " (").first ?? titleWithExtra return title } func updateSongInfo() { let url = URL(string: "https://live.heartfm.com.tr/listen/heart_fm/currentsong")! URLSession.shared.dataTask(with: url) { data, response, error in if let data = data, let songString = String(data: data, encoding: .utf8) { DispatchQueue.main.async { self.currentSong = songString.trimmingCharacters(in: .whitespacesAndNewlines) self.updateAlbumArtUrl(song: self.currentSong) } } }.resume() } private func updateAlbumArtUrl(song: String) { let parts = song.split(separator: "-", maxSplits: 1, omittingEmptySubsequences: true).map { $0.trimmingCharacters(in: .whitespaces) } let artist = parts.first ?? "" let titleWithExtra = parts.count > 1 ? parts[1] : "" let title = titleWithExtra.components(separatedBy: " (").first ?? titleWithExtra let artistAndTitle = artist.isEmpty || title.isEmpty ? song : "\(artist) - \(title)" let encodedArtistAndTitle = artistAndTitle.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? artistAndTitle albumArtUrl = URL(string: "https://www.heartfm.com.tr/ArtCover/\(encodedArtistAndTitle).jpg") }
Posted
by
Post not yet marked as solved
2 Replies
344 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
Post not yet marked as solved
0 Replies
256 Views
Hi, I have few questions regarding the widgets. I would like to know whether widget and app extensions are same ? This link(https://developer.apple.com/app-extensions/) says widget is type of app extension but I am not quite sure as few link in web says they are different. so need to confirm here :) Can a widget share same bundle id as the main app ? so basically can we use the same provisioning profile as the main app? If we use the same bundle id and provisioning profile, will there be any issue during the app store submission process.?
Posted
by