Post

Replies

Boosts

Views

Activity

Conditionally Migrate WatchOS 10 users ONLY to WidgetKit
I'm looking to migrate my users ClockKit complications to WidgetKit in my next app update. I can only do this for WatchOS 10 users because the APIs are too limited for WatchOS 9 (eg. Widget corner round text not available). But I do need to do this for WatchOS 10 users in order to get in the Smart Stack. When I tried to mark my getWidgetConfiguration method in my ComplicationController.swift with: @available(watchOS 10.0, *) it complains and says: Protocol 'CLKComplicationWidgetMigrator' requires 'getWidgetConfiguration(from:completionHandler:)' to be available in watchOS 9.0 and newer I then tried modifying my WidgetKit extension to only support WatchOS 10. This seems to work for a while but at some point WatchOS 9 devices still try the migration and crash with symbolNotFound DYLD issues for the WidgetKit extension which shouldn't even be embedded in the WatchOS 9 builds! (all visible in iPhone Analytics data crashes) So I'm not sure what else to try. I've researched a lot in docs etc... but can find no official way to achieve this.
11
2
3.1k
Jun ’24
Migrating to WidgetKit, issues with editing Watch Faces on iPhone
Anyone who has successfully migrated to using WidgetKit for their Apple Watch complications, your help would be greatly appreciated! I've migrated to WidgetKit for my Watch app. On the Apple Watch Face Editor, the new Widget names and options appear correctly. However, on the iPhone Apple Watch app, it offers both WidgetKit and old ClockKit complications... this should not be. I also have found rendering issues where Watch Faces on the main My Watch tab have blank gaps for WidgetKit complications, when selecting the Watch Face they then render (see photos) I've put in a feedback FB12460375 Have tried a full clear and reinstall of my app on both devices, no change. This issue occurs on WatchOS 9.5.2 / iOS 16.5.1 and WatchOS 10 Beta 2 / iOS 17 Beta 2 Any other ideas?
7
0
2.2k
Sep ’24
Guidance / Documentation on iOS 18.6.1 Blood Oxygen Saturation
Are there any HealthKit related changes to be aware of in the new update that enables SPO2 / Blood Oxygen Saturation measurements on certain Apple Watch models within the US? I’m aware of processing happening on the phone…. But beyond that: Does this mean values are then saved to Apple Health? Do these models still take background SPO2 measurements in the same way as other models do? Are these values then visible in third party iOS apps as normal through HealthKit? Do these values sync back to the paired Apple Watch HealthKit store for third party apps to access on the Watch? For reference I have an iOS and WatchOS app that, amongst other features, provides the ability to see your SPO2 values in the Watch app, complications and in the iOS app.
7
0
256
Sep ’25
How often do I schedule Widget updates?
Classically, the demo in the Meet WidgetKit video used a Calendar as an example, where clearly the times to update are simple to calculate based on when the users events will occur. I'd like to know about the Activity/Fitness Widget. There's no way to tell when a user will burn that next calorie and as far as I can tell, there's still no background observer in HealthKit you can use to call an update on changes. So, with that in mind, how often should I call to update? This same dilemma applies to ClockKit and WatchOS complications.
4
0
2.8k
Jan ’21
Full Keyboard Access causing SwiftUI TabView bug?
I’m having an issue with an app I’ve developed where it grinds to a halt and freezes when using the TabView with a certain iOS Setting enabled. To simplify things, I can easily reproduce this with a demo project. Launch Xcode 12.5, start a new iOS project with swift, swiftUI lifecycle and SwiftUI interface. Then replace the Text code in the content view body with ithe following simple code: TabView { Text("Hello, world! Tab 1")       .tabItem {            Label("Tab 1", systemImage: "list.dash")         }     Text("Tab 2")        .tabItem {            Label("Tab 2", systemImage: "list.dash")         }   } If you launch and run this on device or on the simulator, it all works fine. You can click between the tabs etc… However, if you navigate to the iPhone settings (and this is available in the simulator) and go Accessibility -> Keyboards -> Full Keyboard Access and toggle this ON, it causes a problem. When re-opening the app we just made, as soon as you select a tab at the bottom, the app CPU usage jumps to 100%+ and grinds to a halt. The only fix is to force quite the app, but the issue persists on re-launches until you disable Full Keyboard Access.  Is this a bug? Or am I missing something? It seems to have been around throughout iOS 14’s life time. Thank you
4
0
2.5k
Aug ’22
What's the correct way to check for unavailable API?
I ran into a problem recently with my production app and an update for iOS 18. In this example I was using a new API added to the RC candidate of iOS 18.0, using this API as an example, I couldn't find a satisfactory way to avoid crashing on iOS 18.1 where the API was not available. I had plenty of users running the iOS 18.1 Beta and ultimately it's my fault if a version of my app did work, and then didn't after an update.... This code causes a crash on iOS 18.1 beta as the .appleSleepingBreathingDisturbances API doesn't seem to have made it's way into the beta: if #available(iOS 18.0, *), #available(watchOS 11, *) { healthKitTypesToRead.insert(HKQuantityType.quantityType(forIdentifier: .appleSleepingBreathingDisturbances)!) } I tried this but it still crashed on 18.1: if #available(iOS 18.0, *), #available(watchOS 11, *) { if let newQuantity = HKQuantityType.quantityType(forIdentifier: .appleSleepingBreathingDisturbances) { healthKitTypesToRead.insert(newQuantity) } } In the end the only way I could resolve this was the following: if #available(iOS 18.1, *){ // Do nothing } else if #available(iOS 18.0, *), #available(watchOS 11, *) { if let newQuantity = HKQuantityType.quantityType(forIdentifier: .appleSleepingBreathingDisturbances) { healthKitTypesToRead.insert(newQuantity) } } This seems like a poor solution and I'll have to ensure I release a new version of the app once iOS 18.1 has the available API added to enable support for the feature. How could I have checked availability for this API correctly without causing the app to crash? I'm asking this question more as a Swift language feature rather than issue with the specific API as I'm sure that will get resolved soon anyway. Thanks
4
1
1.2k
Sep ’24
Migrate Widgets from StaticConfiguration to IntentConfiguration
New features in WatchOS 26 with configurable widgets make it more important than ever that apps adopt IntentConfiguration options where applicable. I develop an app with an Apple Watch complication/widget on many many user's Watch faces around the world. I've completed updating my code to support WidgetKit and remove ClockKit. However, I face huge issues adding support for users to configure their widget/complications. If I update a widget to go from StaticConfiguration to IntentConfiguration, even when keeping the "kind" string the same, the widget disappears from the Watch face. This is an unacceptable user experience meaning I can't proceed with the migration. The problem is users will expect me to offer configuration in the Watch face soon for their widget/complication. Currently this process is done in a sub-optimal way in the app itself. A similar issue exists on iOS where the widget will just "freeze" indefinitely is migrated. This issue still occurs on the iOS 26 and WatchOS 26 betas. So how to move this forward. This has been discussed previously here: https://developer.apple.com/forums/thread/661247 I've mentioned it at WidgetKit labs I've filed feedback last year: FB13880020 I've filed feedback this year: FB18180368 It seems really important this gets fixed for developers to adopt these new features, is there any other migration route I'm missing or a workaround that would mitigate this seemingly big problem.
4
1
203
Sep ’25
Getting Large Titles on WatchOS with a Navigation Stack
On my Watch app pre-WatchOS 9 I had code as follows: ` TabView { NavigationView { TodayView(model: delegate.model) .navigationBarTitleDisplayMode(.large) } NavigationView { SettingsView(model: delegate.model) } } .tabViewStyle(.page) However, for WatchOS 9 I'm using the new NavigationStack like this: ` NavigationStack { TabView { TodayView(model: delegate.model) .navigationBarTitleDisplayMode(.large) The issue is, with WatchOS 9 the title always displays as .inline and never large. I've tried embedding a list or scroll view. I've also tried placing a navigationView within the NavigationStack and TabView, that just makes duplicate titles. So, using the NavigationStack with a TabView on WatchOS 9, how do you get large titles? Thanks
3
0
1.7k
Mar ’23
Background Health Store Access for Lock Screen Widgets
It's fairly well know and stated that the Apple Health / HealthKit data store is unavailable when iPhone is locked. Since Lock Screen Widgets were introduced there's been a feature parity mismatch with Apple's own Fitness app which is able to display updating Activity Rings on the Lock Screen. Third party apps cannot do this and have to rely unlocking their device to then trigger an update. This means they often display stale and wrong Health data. With the release of iOS 18 beta, I see no changes to this... Is there anything I've missed? Currently for requesting the Timeline Updates on my Widget I have to just keep requesting updates as often as possible and hope that each time the iPhone might be unlocked.... This is inefficient and a waste of device resources. Even a Widget timeline reload API that let the developer say "Only call update if iPhone unlocked" would be useful.
3
1
1.3k
Jun ’24
AreaMark Always alignsMarkStylesWithPlotArea for linear gradients
I'm trying to make a Swift Chart where 24 AreaMarks an hour apart on X axis over a day display a vertical gradient. The gradient is vertical and is essentially [Color.opacity(0.1),Colour,Color.opacity(0.1] The idea here is where the upper and lower points of each AreaMark are the same or close to each other in the Y axis, the chart essentially displays a line, where they are far apart you get a nice fading vertical gradient. However, it seems that the .alignsMarkStylesWithPlotArea modifier is always set for AreaMarks even if manually applying it false. Investigating further, I've learnt that with AreaMarks in a series, Swift Charts seems to only listen to the first foreground style set in. I've created some sample code to demonstrate this. struct DemoChartView: View { var body: some View { Chart { AreaMark(x: .value("Time", Date().addingTimeInterval(0)), yStart: .value("1", 40), yEnd: .value("2", 60)) .foregroundStyle(LinearGradient(colors: [.pink, .teal], startPoint: .top, endPoint: .bottom)) .alignsMarkStylesWithPlotArea(false) AreaMark(x: .value("Time", Date().addingTimeInterval(3600)), yStart: .value("1", 44), yEnd: .value("2", 58)) .foregroundStyle(LinearGradient(colors: [.orange, .yellow], startPoint: .top, endPoint: .bottom)) .alignsMarkStylesWithPlotArea(false) AreaMark(x: .value("Time", Date().addingTimeInterval(03600*2)), yStart: .value("1", 50), yEnd: .value("2", 90)) .foregroundStyle(LinearGradient(colors: [.green, .blue], startPoint: .top, endPoint: .bottom)) .alignsMarkStylesWithPlotArea(false) } } } Which produces this: So here, all the different .foregroundStyle LinearGradients are being ignored AND the .alignsMarkStylesWithPlotArea(false) is also ignored - the amount of pink on the first mark is different to the second and third 🤷‍♂️ Has anyone encountered this. Are AreaMarks the correct choice or are they just not setup to create this type of data display. Thanks
3
0
758
Jun ’25
Maximise background update on WatchOS
I'm looking to maximise my Watch app's widget to be as up to date as possible. If we imagined the app was a simple step counter, and we wanted to display the users count as up to date as possible. We can conclude: We don't care about widget timelines beyond the current entry as we can't predict the future! We need to refresh the count as often as possible The refresh should be very quick with a straightforward HealthKit query, no networking or heavy work needed. We will assume the user has the complication/widget on their active Watch face. With the standard WidgetKit APIs we can expire the timeline after 15 minutes and in my experimentation a Watch app can usually update its widget timeline at that frequency if it's on the Watch face. I'm experimenting with two methods to try and improve refreshes further A user's step count might not have recently changed when the timeline update is called. I was therefore looking into the HealthKit enableBackgroundDelivery API (which requires the HealthKit Background Delivery entitlement to be enabled) to get updates limited to once an hour from a HKObserverQuery, I can then call the WidgetCenter.shared.reloadAllTimelines() from there. WatchOS also support the BGAppRefreshTaskRequest(identifier:"") and .backgroundTask(.appRefresh) APIs. I can request updates once every 15 minutes here too and then call the WidgetCenter.shared.reloadAllTimelines(). With option 1, this update opportunity is great as it will specifically update when there's new steps so even once an hour this would be helpful (A real shame to be limited to once an hour even if this used up WidgetKit standard reload budgets: FB13879817, FB11677132, FB10016177). But I can't determine if this update takes away one of the standard timeline expiration updates that already run 4 times an hour? Could I observe additional Health types to get additional updates? Do I need the Background Modes Capability as well as the HealthKit Background Delivery for this in Xcode or just the HealthKit one? With option 2, I can't find a suitable option in the (short) list of supported background modes in Xcode. Does not selecting any mean my app will get 0 refreshes from this route and so should not be implemented in my use case?
3
1
166
Jun ’25
Sleep Score API access
New in iOS 26 and WatchOS 26 is a Sleep Score calculation for users based on Duration, Bedtime and Interruptions. Unfortunately I can't find any APIs for developers to tap into this metric. Yes, in theory it's all created off the same Sleep Analysis data already available with HealthKit but that makes it very hard to recreate in our apps. If the numbers don't match up exactly, users will understandably complain. Can anyone confirm that this is the case and I've not missed a Sleep Score API? I'll then file feedback. Hopefully this doesn't go the way of Heart Rate Zones where the Apple Watch iPhone app has generated them for years and provided no way for third party apps to access these values (yes many feedbacks provided previously).
3
1
228
Sep ’25
How can I apply the modify my Swift Chart based on the ComplicationRenderingMode
For Apple Watch complications displayed on tinted faced, developers can use: @Environment(\.complicationRenderingMode) var renderingMode to see if the watch face is tinted. You can then use the .complicationForeground() modifier to set elements of the complication to match that tint color. (I appreciate that .complicationForeground() is now deprecated in favour of .widgetAccentable() but I believe the behaviour is the same). However, this can only be applied to a view I believe. I'd like to display a Swift Chart where only certain elements of the chart have the .complicationForeground() rather than the whole chart. For example, in one case I'd like the LineMark to pop with the tinted color of the complication whilst the rest of the complication get the gray default tint. Is there a way to do with with the current APIs? Thanks
2
0
1.2k
Apr ’23
openSettingsURLString For Privacy & Security -> Health
How can I open the user's Health Privacy Settings directly from my app when I'd like them to review them? I believe similar questions have been asked before like this one: https://forums.developer.apple.com/forums/thread/730434 However, I'm wondering if the situation is changed for iOS 17 or if there's a way that works for Health permissions. This is directly possible in the Garmin Connect app for example which is a major app on the store.
2
0
1.6k
Apr ’24