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.

Posts under WidgetKit tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

WidgetKit Not running in iOS 14/15 (FBSOpenApplicationServiceErrorDomain)
I was adding WidgetExtension target for my old project. The widget target is running fine in iOS 17, In my case, widget need to support iOS 14 and above, so I updated my widget code to old style, To removing WidgetConfigurationIntent and AppIntentTimelineProvider. import WidgetKit import SwiftUI struct Provider: TimelineProvider { func placeholder(in context: Context) -> SimpleEntry { SimpleEntry() } func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) { completion(SimpleEntry()) } func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) { completion(Timeline(entries: [SimpleEntry()], policy: .never)) } typealias Entry = SimpleEntry } struct SimpleEntry: TimelineEntry { let date: Date = Date() } struct NCWidgetEntryView : View { var entry: Provider.Entry var body: some View { VStack { Text("Time:") Text(entry.date, style: .time) } } } struct NCWidget: Widget { let kind: String = "NCWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in NCWidgetEntryView(entry: entry) } .configurationDisplayName("DisplayName") .description("description") } } In my case, the code was working fine in iOS 17 simulator, But if I try to run in iOS 15, it returns the below error code-SendProcessControlEvent:toPid: encountered an error: Error Domain=com.apple.dt.deviceprocesscontrolservice Code=8 "Failed to show Widget 'com.name-pprd.NCWidgetExtension' 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=0x600003570b40 {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.name-pprd.NCWidgetExtension' 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=0x600003570b40 {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=0x600003570bd0 {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=0x600003570b40 {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-07-20 17:30:58 +0000"; } -- System Information macOS Version 14.5 (Build 23F79) Xcode 15.0.1 (22266) (Build 15A507) Timestamp: 2024-07-20T23:00:58+05:30 In widget target Minimum target is 14.0 In App target Minimum target is 13.0
1
0
109
1d
onContinueUserActivity not working on first app launch
HI, I'm trying to deeplink from my widget to a view in my app. I'm using the "SwiftUI app lifecycle". This the code I'm currently using: var body: some Scene { WindowGroup { RootView() .onContinueUserActivity("NextDeparturesWidgetConfigurationIntent") { userActivity in guard let configuration: NextDeparturesWidgetConfigurationIntent = userActivity .widgetConfigurationIntent(), let stationEntity = configuration.stationEntity else { return } NotificationCenter.default.post(name: .onOpenStation, object: stationEntity.id) } } } It is working fine when the app is already running (in the background). However when the app is "cold starting" (ie. not in memory) onContinueUserActivity is never called. I tried adding a UIApplicationDelegateAdaptor: func application( _ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions ) -> UISceneConfiguration { if let userActivity = options.userActivities.first { let configuration: NextDeparturesWidgetConfigurationIntent? = userActivity.widgetConfigurationIntent() // casting fails } return UISceneConfiguration( name: nil, sessionRole: connectingSceneSession.role ) } I can see that the activity is received but it is never casted to NextDeparturesWidgetConfigurationIntent. What am I missing ?
0
0
58
1d
ControlConfigurationIntent won't open the app despite setting openAppWhenRun = true
I am working on building Control widgets for our app and have noticed that openAppWhenRun doesn't seem to work for any ControlConfigurationIntent. When attaching the debugger to the widget extension in a sample project, I see the following error: Unknown NSError The operation couldn’t be completed. (LNActionExecutorErrorDomain error 2018.) This is reproducible as of Xcode 16.0 Beta 2 and Beta 3. I have noted that using an OpenIntent, with a parameter called target that conforms to AppEnum seems to open the app properly, but if I use that workaround, adding any additional parameters to the OpenIntent seems to break things again. Are others seeing this issue? I have feedback FB14357691. Here's some sample code below to reproduce: var body: some ControlWidgetConfiguration { AppIntentControlConfiguration(kind: "Open Any Screen", intent: OpenAppScreenIntent.self) { template in ControlWidgetButton(action: template) { Label { Text("Open App") } icon: { Image(systemName: "calendar") } }.tint(.red) } } } enum AppScreen: CaseIterable { case calendar case campus case search var title: String { switch self { case .calendar: "Calendar" case .campus: "Campus" case .search: "Search" } } } struct OpenAppScreenIntent: ControlConfigurationIntent { static var title: LocalizedStringResource = "Open app to a screen" static var description = IntentDescription("Opens the app.") /// The app should open regardless of what happens here static let openAppWhenRun: Bool = true @Parameter(title: "Screen", optionsProvider: OsuScreenOptionsProvider()) var screen: String? struct OsuScreenOptionsProvider: DynamicOptionsProvider { func results() async throws -> ItemCollection<String> { var screenTitles: [String] = [] for screen in AppScreen.allCases { async let title = screen.title await screenTitles.append(title) } return ItemCollection { ItemSection(items: screenTitles.map { IntentItem($0)}) } } func defaultResult() async -> String? { return "Campus" } } @MainActor func perform() async throws -> some IntentResult { #warning("The app should open regardless of what happens in this method, but it doesn't") return .result() } }
5
0
124
3d
Error generating files in compilation cause AppEntity and Widget Extension on iOS17
When I add AppEnity to my model, I receive this error that is still repeated for each attribute in the model. The models are already marked for Widget Extension in Target Membership. I have already cleaned and restarted, nothing works. Will anyone know what I'm doing wrong? Unable to find matching source file for path "@_swiftmacro_21HabitWidgetsExtension0A05ModelfMm.swift" import SwiftData import AppIntents enum FrecuenciaCumplimiento: String, Codable { case diario case semanal case mensual } @Model final class Habit: AppEntity { @Attribute(.unique) var id: UUID var nombre: String var descripcion: String var icono: String var color: String var esHabitoPositivo: Bool var valorObjetivo: Double var unidadObjetivo: String var frecuenciaCumplimiento: FrecuenciaCumplimiento static var typeDisplayRepresentation: TypeDisplayRepresentation = "Hábito" static var defaultQuery = HabitQuery() var displayRepresentation: DisplayRepresentation { DisplayRepresentation(title: "\(nombre)") } static var allHabits: [Habit] = [ Habit(id: UUID(), nombre: "uno", descripcion: "", icono: "circle", color: "#BF0000", esHabitoPositivo: true, valorObjetivo: 1.0, unidadObjetivo: "", frecuenciaCumplimiento: .mensual), Habit(id: UUID(), nombre: "dos", descripcion: "", icono: "circle", color: "#BF0000", esHabitoPositivo: true, valorObjetivo: 1.0, unidadObjetivo: "", frecuenciaCumplimiento: .mensual) ] /* static func loadAllHabits() async throws { do { let modelContainer = try ModelContainer(for: Habit.self) let descriptor = FetchDescriptor<Habit>() allHabits = try await modelContainer.mainContext.fetch(descriptor) } catch { // Manejo de errores si es necesario print("Error al cargar hábitos: \(error)") throw error } } */ init(id: UUID = UUID(), nombre: String, descripcion: String, icono: String, color: String, esHabitoPositivo: Bool, valorObjetivo: Double, unidadObjetivo: String, frecuenciaCumplimiento: FrecuenciaCumplimiento) { self.id = id self.nombre = nombre self.descripcion = descripcion self.icono = icono self.color = color self.esHabitoPositivo = esHabitoPositivo self.valorObjetivo = valorObjetivo self.unidadObjetivo = unidadObjetivo self.frecuenciaCumplimiento = frecuenciaCumplimiento } @Relationship(deleteRule: .cascade) var habitRecords: [HabitRecord] = [] } struct HabitQuery: EntityQuery { func entities(for identifiers: [Habit.ID]) async throws -> [Habit] { //try await Habit.loadAllHabits() return Habit.allHabits.filter { identifiers.contains($0.id) } } func suggestedEntities() async throws -> [Habit] { //try await Habit.loadAllHabits() return Habit.allHabits// .filter { $0.isAvailable } } func defaultResult() async -> Habit? { try? await suggestedEntities().first } }
3
2
458
4d
ControlWidget in iOS 18 Beta not showing and the widget created prior to iOS18 Beta not showing too.
I tried creating a ControlWidget following this Apple document - https://developer.apple.com/documentation/widgetkit/creating-controls-to-perform-actions-across-the-system, but for some reason the Control is not showing while I am trying to add and on top of that the widget which we created prior to iOS18 is also not showing, while trying to add. Here is the gist of code : struct WidgetLauncher{ static func main() { if #available(iOSApplicationExtension 18.0, *) { appWidgetsFor18.main() } else { appWidgets.main() } struct apptWorkWidgets: WidgetBundle { var body: some Widget { WidgetPriorToiOS18() } } @available(iOSApplicationExtension 18.0, *) struct appWidgetsFor18: WidgetBundle { var body: some Widget { WidgetPriorToiOS18() PerformActionButton() //This from the apple's document. } } @available(iOSApplicationExtension 18.0, *) struct PerformActionButton: ControlWidget { var body: some ControlWidgetConfiguration { StaticControlConfiguration( kind: "com.example.myApp.performActionButton" ) { ControlWidgetButton(action: PerformAction()) { Label("Perform Action", systemImage: "checkmark.circle") } } .displayName("Perform Action") .description("An example control that performs an action.") } } struct PerformAction: AppIntent { static let title: LocalizedStringResource = "Perform action" func perform() async throws -&gt; some IntentResult { // Code that performs the action... return .result() } }
0
0
102
4d
"Unknown extension process" is displayed after app updating
Hello. In iOS 17, after updating the app, when trying to "Edit Widget" from a long press on the widget, "Unknown extension process" is displayed and the widget cannot be edited. At this time, the widget becomes completely white (or completely black), and it cannot be fixed without restarting the iPhone. This issue occurs sporadically on some devices. The implementation uses AppIntentTimelineProvider. Does anyone know a solution, workaround, or the cause of this problem? Thank you.
0
0
101
5d
The button click for real-time activity did not work.
We added a button in the real-time activity that responds within the app upon clicking. Now we're encountering an issue where, if you immediately click this button after swiping down to enter the notification center, it only opens the app without any scheme response. You have to wait for about 1 second after swiping down before the button can respond normally. Could you please tell us why this is happening?
1
0
173
5d
WidgetBundle with ControlWidget does not work on iOS 17
I'm trying to add a ControlWidget to my WidgetBundle like this: struct MyWidgets: WidgetBundle { var body: some Widget { if #available(iOSApplicationExtension 18.0, *) { LauncherControl() } MyLiveActivityWidget() HomeScreenWidget() LockScreenWidget() } This works exactly as expected on iOS 18. However on iOS 17 my app seems to have no widgets at all. The workaround described here (https://www.avanderlee.com/swiftui/variable-widgetbundle-configuration/) does not work either since WidgetBundleBuilder.buildBlock does not accept ControlWidget as an argument. What is the correct way to include a Control widget conditionally on iOS 18?
1
0
273
5d
How should a Widget communicate with the main app's Audio objects
If I have an interactive widget, with button that triggers an AudioPlaybackIntent, how should the intent communicate with the main app's audio player to pause/play? I was thinking about instantiating the player in the Widget explicitly in its lifecycle. But, if the audio player gets instantiated separately in the app and in the widget, wouldn't I have two players running? Or am I misunderstanding the setup?
0
0
129
1w
Widgets Not Refreshing Timelines
I'm making an app where there are two widgets. Both widgets are supposed to get their timelines once per day, as all data for the day is known at midnight. I'm having an issue where when put on a development device, the widgets' timelines work correctly, but do not refresh the next day. I've tried both .atEnd and .after(Date) refresh policies and neither seems to work. Does anyone know why the widget isn't refreshing properly? I'm almost certain that I'm under the daily limit of refreshes (one timeline refresh and ~12 timeline entries per day). Thank you for any help! Dev device iPhone 15 Pro on 17.5.1 (21F90) with Xcode Version 15.4 (15F31d). Below is the timeline code for one of the widgets: struct EndTimeProvider: TimelineProvider { var currentHour: Int { Calendar.current.component(.hour, from: .now) } var currentMinute : Int { Calendar.current.component(.minute, from: .now) } var placeholderSixthPeriod: Period { var endMinute: Int = 0 var endHour: Int = 0 if currentMinute > 60-14 { endHour = currentHour + 1 endMinute = (currentMinute + 14) % 60 } else { endHour = currentHour endMinute = currentMinute + 14 } return Period(name: "Period 6", start: "00:00", end: "\(endHour):\(endMinute)") } func placeholder(in context: Context) -> EndTimeEntry { return EndTimeEntry(date: .now, displayPeriod: placeholderSixthPeriod, scheduleName: "Regular Day") } func getSnapshot(in context: Context, completion: @escaping (EndTimeEntry) -> ()) { if context.isPreview { completion(placeholder(in: context)) return } let entry = EndTimeEntry(date: .now, displayPeriod: placeholderSixthPeriod, scheduleName: "Regular Day") completion(entry) } func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) { var entries: [EndTimeEntry] = [] let context = PersistenceController.shared.backgroundContext let scheduleFetch = StoredScheduleOnDate.fetchRequest() do { let storedSchedules = try context.fetch(scheduleFetch) let currentDate = Date() if let todaySchedule = storedSchedules.first(where: { Calendar.current.isDate($0.date!, equalTo: currentDate, toGranularity: .day) })?.schedule?.asDayType() { // Have an entry at midnight when schedules are needed let morningStart = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: .now)! let morningPeriod = Period(name: "Good morning", start: "00:00", end: todaySchedule.periods.first!.start) let morningEntry = EndTimeEntry(date: morningStart, displayPeriod: morningPeriod, scheduleName: todaySchedule.name) entries.append(morningEntry) // Passing periods should show the next full period's end time. // This means that an entry's date should be the past period's end, or the start in the first period's case. let firstPeriod = todaySchedule.periods.first! let firstPeriodEntry = EndTimeEntry(date: firstPeriod.getStartAsDate(), displayPeriod: firstPeriod, scheduleName: todaySchedule.name) entries.append(firstPeriodEntry) for index in 1..<todaySchedule.periods.count { let entry = EndTimeEntry(date: todaySchedule.periods[index-1].getEndAsDate(), displayPeriod: todaySchedule.periods[index], scheduleName: todaySchedule.name) entries.append(entry) } // Have an entry at the end of the day to have the start time of the next day shown if let tomorrowSchedule = storedSchedules.first(where: { Calendar.current.isDate($0.date!, equalTo: Calendar.current.date(byAdding: .day, value: 1, to: currentDate)!, toGranularity: .day) })?.schedule?.asDayType() { // At EOD, show tomorrow's start let endOfDay: Date = todaySchedule.periods.last!.getEndAsDate() let overnightPeriod: Period = Period(name: "Good night", start: todaySchedule.periods.last!.end, end: "00:00") let overnightEntry = EndTimeEntry(date: endOfDay, displayPeriod: overnightPeriod, scheduleName: tomorrowSchedule.name, overrideDisplayDate: tomorrowSchedule.periods.first!.getStartAsDate()) entries.append(overnightEntry) } } } catch { fatalError("Could not fetch from Core Data for widget timeline. \(error)") } let tomorrowMorning = Calendar.current.date(bySettingHour: 0, minute: 1, second: 0, of: Calendar.current.date(byAdding: .day, value: 1, to: .now)!)! let timeline = Timeline(entries: entries, policy: .after(tomorrowMorning)) completion(timeline) } } struct EndTimeEntry: TimelineEntry { let date: Date let displayPeriod: Period let scheduleName: String let overrideDisplayDate: Date? init(date: Date, displayPeriod: Period, scheduleName: String, overrideDisplayDate: Date) { self.date = date self.displayPeriod = displayPeriod self.scheduleName = scheduleName self.overrideDisplayDate = overrideDisplayDate } init(date: Date, displayPeriod: Period, scheduleName: String) { self.date = date self.displayPeriod = displayPeriod self.scheduleName = scheduleName self.overrideDisplayDate = nil } } ...
2
0
171
1w
Updating watchOS complication when data in iOS app changes.
Hello, I'm facing problems when attempting to update my watchOS complication when relevant data on the iPhone app changes. From what I gather reading the documentation I have to use the Watch Connectivity Framework to send said new data from the phone to the watch: use transferCurrentComplicationUserInfo() to send a dictionary of data from the phone to the watch implement the didReceiveUserInfo delegate method to handle incoming data on the watch in said handler, save the incoming data to UserDefaults using an App Group so the widget-extension can read that data after saving the data to UserDefaults, call WidgetCenter.shared.reloadAllTimelines() so watchOS can request fresh timelines for my complications change the getTimeline() method of my TimelineProvider so it uses the received data from UserDefaults OR async fetch fresh data if received data from phone is too old If I understand correctly, transferCurrentComplicationUserInfo() is limited to be used a maximum of 50 times a day. I'm running the apps in debug mode, so this should be no problem. Here is my current implementation: 1 : Setup of my WC class: final class Connectivity: NSObject { // singleton approach static let shared = Connectivity() // used to rate limit transmissions from phone → watch private var lastSentBalanceContext: Date? = nil private override init() { super.init() // no need to check availability on watchOS #if !os(watchOS) guard WCSession.isSupported() else { return } #endif WCSession.default.delegate = self WCSession.default.activate() } } 2 : The method enabling transmission from phone to watch: #if os(iOS) extension Connectivity: WCSessionDelegate { func sendBalanceContext(sample: HealthData) { guard WCSession.default.activationState == .activated else { return } guard WCSession.default.isWatchAppInstalled else { return } // rate limitat transmissions guard self.lastSentBalanceContext == nil || abs(Date.now.timeIntervalSince(self.lastSentBalanceContext!)) > 10 else { return } if WCSession.default.remainingComplicationUserInfoTransfers > 0 { WCSession.default.transferCurrentComplicationUserInfo([ "context": "balance", "date": sample.date, "burnedActive": sample.burnedActive, // more data... ]) self.lastSentBalanceContext = .now } } // boilerplate handlers here } #endif 3 : Delegete method that handles incoming data on the watch: #if os(watchOS) extension Connectivity: WCSessionDelegate { func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) { guard let context = userInfo["context"] as? String, context == "balance" else { return } guard let date = userInfo["date"] as? Date, let burnedActive = userInfo["burnedActive"] as? Int /* more data... */ else { return } guard let SharedDefaults = UserDefaults(suiteName: "group.4DXABR577J.com.count.kcal.app") else { return } // TimelineProvider uses this to determine wether to use this data or fetch data on its own SharedDefaults.set(Date.now, forKey: "lastReceivedBalanceContext") SharedDefaults.set(date, forKey: "date") SharedDefaults.set(burnedActive, forKey: "burnedActive") // more data... WidgetCenter.shared.reloadAllTimelines() } // boilerplate handlers } #endif 4 : Finally, the TimelineProvider: struct HealthDataEntry: TimelineEntry { let date: Date let data: HealthData } struct HealthDataTimelineProvider: TimelineProvider { // other callbacks here func getTimeline(in context: Context, completion: @escaping (Timeline<HealthDataEntry>) -> Void) { let SharedDefaults: UserDefaults = UserDefaults(suiteName: "group.4DXABR577J.com.count.kcal.app")! let nextUpdateDate = Calendar.current.date(byAdding: .minute, value: 15, to: .now)! // use data from phone if it is less than 60 seconds old if let lastReceivedBalanceContext = SharedDefaults.object(forKey: "lastReceivedBalanceContext") as? Date { let interval = lastReceivedBalanceContext.timeIntervalSince(.now) if interval > -60 && interval <= 0 { let data = HealthData(date: SharedDefaults.object(forKey: "date") as? Date ?? Date(timeIntervalSinceReferenceDate: 0), burnedActive: SharedDefaults.integer(forKey: "burnedActive"), burnedActive7: SharedDefaults.integer(forKey: "burnedActive7") /* other data ... */) let timeline = Timeline( entries: [HealthDataEntry(date: .now, data: data)], policy: .after(nextUpdateDate) ) completion(timeline) return } } // default: fetch from HealthKit (if received data from phone is > 60s) Task { let timeline = Timeline( entries: [HealthDataEntry(date: .now, data: try! await asyncFetchData())], policy: .after(nextUpdateDate) ) completion(timeline) } } } The issue I am facing is that the watchOS complication only gets refreshed when I acitvely build and run the watchOS app in Xcode and then initiate a transmission of data to the watch. This works even if I do it back to back to back. As soon as I stop the watchOS app from within Xcode, my complications won't update anymore. I noticed this behavior when I used print() statements throughout my code to see whether it is beeing executed as expected. The iPhone sends data, the watch receives it but then the watch fails to update the complications ONLY when not running from Xcode. Can you spot any flaws in my implementation or in my understanding? Maybe transferCurrentComplicationUserInfo() just isn't as reliable as I think it should be? I interpreted it as being practically guaranteed to refresh the complications 50 times a day, pretty much instantly? Any help or guidance would be greatly appreciated!
1
0
208
1w
Non-tinted image in complications using WidgetKit
I have a watchOS app where a user can select a picture. I’d like the picture to be displayed in a complication. I’m using WidgetKit, and I found out that for some watch faces (rendering mode = accented), the image gets tinted. Instead of the picture, the user sees only a colored box. It appears that using the old framework, ClockKit, it was possible to display an image that gets slightly colored with the tint color on tinted watch faces. I believe this is to ensure backward compatibility of old complications. My question is: can I do the same using WidgetKit? I tried using the widgetAccentable() modifier, but it doesn’t work. Here's an example of what I mean. In the middle complication, instead of the pink square, I'd like to display the user picture.
5
1
249
1w
Live Activity Text Style Issue in iOS Simulator's lock screen (iOS 17.2)
Environment: iOS Version: 17.2 iOS Simulator Version: 17.2 Xcode Version: 15.2 Device: iPhone 15 Pro Max App Target Version: iOS 17.2 Preconditions: App with Live Activity feature is installed. Device/Simulator is running iOS 17.2. Steps to Reproduce: Start the app and initiate a Live Activity with text styled as .timer. Lock the device screen or switch to the lock screen view in the iOS Simulator. Observe the Live Activity on the lock screen, noting the text style. Unlock the device. This time noting the .timer changed its style. The text style of the Live Activity remains consistent both on the lock screen and after unlocking the device, maintaining its .timer style throughout its lifecycle. Frequency: Occurs every time the steps are reproduced.
4
2
537
1w
Live Activity compact timers
The Human Interface Guidelines for Live Activities provide several examples of compact presentations that have a timer counting down formatted like "3min" or "3m", similar to the timers in the Clock app. Such examples can be found in this Stack Overflow question: https://stackoverflow.com/questions/77551496/is-it-possible-to-make-an-only-minutes-1m-countdown-in-a-live-activity A Timer initialized with init(timerInterval:pauseTime:countsDown:showsHours:) has provided a live countdown timer in widgets and live activities, but the formatting is limited. And since live activities come with limitations that prevent us from using Timers, there's no real way to implement this kind of thing ourselves. What is Apple's official guidance for implementing this kind of timer for the compact presentation?
3
2
317
1w
iOS18, interactive widget not respond (AppIntent not working)
here is my case: i add the AppIntent to both your app and widget extension targets. the intent will run my app process when app is running. it works perfectly on iOS 17. but iOS 18, my app process never called. i download app's demo, https://developer.apple.com/documentation/widgetkit/emoji-rangers-supporting-live-activities-interactivity-and-animations it looks like the same issue. it runs well because even it runs in the widget extension target, it still can present expected UI. but in real case, we need to run the app process to do some work. by debugging, i found the app process never called(set breakpoint). i add openAppWhenRun, it works well on iOS 18. but it will open the app when the widget is running. it is not what i want.
1
1
256
1w
[Live Activity / Dynamic Island] Countdown Timer issues (ending activity, styling)
Hello! I'm building a Countdown Timer for the Dynamic Island using a Live Activity. I have two issues for which I can't find any solution: We want to display the time in the "X minutes" format, like in this example. I went through the forum but all the answers were wrong, because they were using a Text(:format) which never updates in the live activity, or a Text(:timerInterval) which we can't format. I want the Live Activity to end once the timer gets to zero. I found this staleDate parameter that I thought would helped, but is actually only adding loaders on my design once the date is reached. I tried to implement a solution like the answer of this post, but the if (context.isStale) {...} part is never being rendered. It also looks like the stale sate gets activated only when the app is focus again. I tried several fixes, went through a lot of forum and posts, but I can't find any solution. Thanks!
0
0
147
1w