ClockKit

RSS for tag

Display app-specific data in the complications on the clock face using ClockKit.

Posts under ClockKit tag

36 Posts

Post

Replies

Boosts

Views

Activity

Signing / Provisioning Profile Error After Enabling CloudKit + MusicKit Entitlements
Hi everyone, after enabling CloudKit in my project, my app started showing conflicts between MusicKit and CloudKit entitlements — and now Xcode is failing to generate the provisioning profile entirely. Current issue (Signing / Provisioning Profile Failure) Xcode shows this error: “Provisioning profile ‘iOS Team Provisioning Profile: team8.groovefy.dev’ doesn’t include the entitlements: com.apple.developer.media-library, com.apple.developer.music-user-token, com.apple.developer.musickit, com.apple.developer.playable-content, com.apple.security.exception.mach-lookup.global-name” Automatic signing fails, and Xcode cannot create or update the provisioning profile. This started right after CloudKit was enabled in the project. Context Before enabling CloudKit, MusicKit worked normally, including Apple Music authentication and playlist creation. After activating CloudKit capabilities: MusicKit stopped generating the Apple Music user token Playlist creation broke Now the provisioning profile cannot be rebuilt because the required MusicKit-related entitlements are no longer included Even after removing CloudKit entirely, the issue persists — as if the App ID or entitlements on the server side became inconsistent or corrupted. I already tried: Recreating App Identifier Recreating provisioning profiles Resetting capabilities Cleaning and reinitializing the Xcode project settings But Xcode still refuses to generate a valid provisioning profile that includes the MusicKit entitlements. Summary Enabling CloudKit caused MusicKit entitlements to collide, and now the provisioning profile no longer includes the required MusicKit entitlements — preventing the app from signing, running, or creating playlists. If anyone has faced this type of entitlements/provisioning corruption or knows how to reset the App ID entitlements on Apple’s side, any help would be greatly appreciated.
1
0
280
Dec ’25
Complex functions are not available
When I generate a dial through code, it prompts the following content: code: CLKWatchFaceLibrary * lib = [[CLKWatchFaceLibrary alloc] init]; [lib addWatchFaceAtURL:url completionHandler:^(NSError * _Nullable error) { }]; result: Complex functions are not available How to fix it? Make it usable, Thank you~
1
0
944
Dec ’24
ClockKit to WidgetKit migration bug
Hi, I'm migrating ClockKit complications to WidgetKit. Everything works well except when I run the WidgetKit version, I see complications appear twice each in the complications list for my app when adding them. If I restart the app from Xcode, it won't happen again, only for the first time. But on the actual device, only Watch restart or app reinstall fixes it which is frustrating and would not be ideal for live users. I even tried Apple's example ClockKit project -> added complications to watch face -> added WidgetKit target, CLKComplicationWidgetMigrator and func widgetConfiguration(from complicationDescriptor: CLKComplicationDescriptor) code -> run the app -> new complications appear correctly replacing old ones -> when hold to add/change complications I see it doubled (screenshot attached) and it's even selected twice If I add more complications, they will appear two times as well except one selected in two places almost like it's two same lists created. class ComplicationController: NSObject, CLKComplicationDataSource, CLKComplicationWidgetMigrator { @available(watchOSApplicationExtension 9.0, *) var widgetMigrator: CLKComplicationWidgetMigrator { self } @available(watchOSApplicationExtension 9.0, *) func widgetConfiguration(from complicationDescriptor: CLKComplicationDescriptor) async -> CLKComplicationWidgetMigrationConfiguration? { switch complicationDescriptor.identifier { case "Coffee_Tracker_Caffeine_Dose": return CLKComplicationStaticWidgetMigrationConfiguration( kind: "WidgetKitComplications", extensionBundleIdentifier: "com.example.apple-samplecode.Coffee-Tracker.watchkitapp.watchkitextension.WidgetKitComplications") default: return nil } }
4
0
953
Sep ’24
ClockKit Complications not working with Xcode 14 single-target watchOS app
I’ve created a single-target watchOS app in Xcode 14, but I can’t seem to get ClockKit complications working. I’ve added a CLKComplicationDataSource class to my watch target, and in the Info pane for my target I have set the CLKComplicationPrincipalClass key to MODULE-NAME.ComplicationController I haven’t yet added Complication placeholder images to my Assets.xcassets, but as far as I am aware, that shouldn’t be a problem while I am still testing. However, when I run it on a watchOS simulator, the complications never show up on the watch complications list when adding a complication. All of the tutorials I can find for ClockKit complications reference older two-target WatchKit apps. Do the newer single target apps no longer support ClockKit? If so, how can I make a two-target WatchKit app with Xcode 14? Unfortunately I cannot use WidgetKit for my complications because I need to support watchOS 7 at least, and WidgetKit only supports watchOS 9+ Thanks for your help
3
1
2.3k
Aug ’24
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
1.4k
Jul ’24
Extract metadata from a .watchface
Hello, fellow developers! How would you approach .watchface file to extract it's metadata? I need to know in which version of the app the face was created, to prompt the user to update the app if necessary. Looking at binary I suppose that a .watchface file consists of a PNG previews and JSON metadata and it all packed in one file somehow. Probably archived with gzip.
0
0
678
Jul ’24
Major Clock app suggestion
When you use set an Alarm in clock app, you get to choose mutliple tones and even songs from Apple music. However, when you set a Sleep|Wake up alarm using a sleep schedule, you are prompted to choose only limited tones. This limits the Alarm tone options for sleep one. Hope, Apple lets users pick the full library of tones in next update.
1
0
707
Jun ’24
Complication works on watch, but not visible in watch app on phone
I have an iPhone app, and added watch support, including a simple launcher complication. I can add the complication using the edit UI on the watch, but the complication is not visible using the watch app on the iPhone. When I add my complication on the watch and then open the watch app on the iPhone, the complication slot shows as "Off". What could I be doing wrong?
2
0
892
Jun ’24
`WCSession.isComplicationEnabled` is `false` when complication is in Smart Stack
⌚️Hello, I've noticed in watchOS 10 that when a complication is in the Smart Stack, the value of WCSession.isComplicationEnabled is false. I'm not sure if this is intentional or a bug. It seems trivial at first glance, but it actually affects the communication mechanism mentioned in Implementing Two-Way Communication Using Watch Connectivity. In the following two scenarios, if the user has only added the app's complication to the Smart Stack, then the watch app will not be able to communicate properly with the iOS app. Scenario 1 - WCSession.transferCurrentComplicationUserInfo() // update complications from the iOS app if WCSession.default.isComplicationEnabled { let userInfoTransfer = WCSession.default.transferCurrentComplicationUserInfo(userInfo) // ... } As described in Implementing Two-Way Communication Using Watch Connectivity, when the iOS app proactively updates the data of the watch app, since WCSession.isComplicationEnabled is false, WCSession will refuse to transfer any data. This causes the standalone complication in Smart Stack to not be updated. Scenario 2 - WKApplicationRefreshBackgroundTask When the watch app uses WKApplication.scheduleBackgroundRefresh() to periodically update data, as long as the user has added the app's complication to the watch face, the corresponding WKApplicationRefreshBackgroundTask can be executed periodically in the background to fetch data. However, if the user has only added complication to the Smart Stack, then the watch app will be completely purged, and the background task will not be executed at all. Although WCSession.isComplicationEnabled is not directly used in this scenario, its behavior appears to be the same, that is, the complication in the Smart Stack is not considered a complication by the system. Should I submit a bug report?
2
0
1.3k
Feb ’24
How can I re-create a CLKRelativeDateTextProvider in a WidgetKit complication?
I'm in the process of migrating one of my app's Apple Watch complications from ClockKit to WidgetKit. In my ClockKit complications, there are some cases where a show the relative time since the last event in the app (for example, "25MIN"). With ClockKit, this was quite straightforward using a CLKTextProvider designed for this exact purpose: CLKRelativeDateTextProvider(date: date, style: .offsetShort, units: [.hour, .minute]) This has always worked great, since it lets me specify that hours and minutes should be used, but not seconds, since they're not relevant here. How can I accomplish the same thing with WidgetKit and SwiftUI? The closest thing I've found is this: Text(date, style: .relative) It shows, for example: 14MIN 8SEC This is not what I want, since it shows seconds. It makes the complication look messy with all the extra information, and is distracting because it updates every second until an hour has passed. I suppose I could write my own logic to create a new timeline entry every minute to show the number of hours and minutes since the last update, but since CLKTextProvider works so nicely I wanted to check whether there is some way to accomplish the same thing without creating a new entry for every minute. There seem to be some more customizable options with date formatters, but I haven't found a way to combine this with the SwiftUI version that updates automatically on the Apple Watch face: https://developer.apple.com/documentation/foundation/date/relativeformatstyle/3766585-presentation
4
0
1.1k
Oct ’23
Userdefaults for complications are nil while watch is working fine
I'm able to successfully send userdefaults from the phone to the watch using applicationContext and save those userdefaults to the app group I created. For the watch, I see all the userdefaults come in successfully and I'm able to use them in the WatchOS app. Once I created the complications for the watch app, I am using the same app group ID and I added that app group in the capabilities of the watch extension but when I try to use the same userdefault that I'm using for the watch, everything is nil. I'm not understanding what I'm doing wrong. How do I share userdefaults between the watch and complication? This is how I'm bringing in the userdefaults from the phone to the watch let defaults = UserDefaults(suiteName: K.appGroupID) if let value1 = applicationContext["lat"] as? Double { defaults?.setValue(value1, forKey: "lat") } if let value2 = applicationContext["lng"] as? Double { defaults?.setValue(value2, forKey: "lng") } ... I am able to use this exact function in the watch app, but in the complication, the userdefault is nil. let formatter = DateFormatter() formatter.timeStyle = .short formatter.timeZone = .current let defaultLoad = UserDefaults.init(suiteName: K.appGroupID) if defaultLoad!.bool(forKey: "timeFormat") == true { ... I tried to remove and re-add the app group but that didn't work either. I also created a separate app group for the watch and extension to use alone but still same issue.
4
1
2.2k
Aug ’23
Bluetooth ANCS don't send ringing alarm clock and countdown timer
Hello everyone, sorry for my ignorance about it, with ANCS I managed to get all the notifications except the alarm that rings and the timer expired, where am I wrong? do they travel on other channels like gatt? if yes can someone help me understand how to receive these 2 information? the alarm goes off and the timer expired? Thanks in advance to everyone who will help me, Marco.
1
0
1.3k
Aug ’23
Migrating ClockKit complications to WidgetKit not working
I've implemented delegate method suggested in the article https://developer.apple.com/documentation/widgetkit/converting-a-clockkit-app and double (even triple) checked kind and extensionBundleIdentifier of my StaticConfiguration But when I install the app version containing WidgetKit complications they don't replace old ones from ClockKit on the watch face. In the same time old complications are not displayed - I see empty slots. When I check setup in Watch app on the phone I see that old complications remain assigned. If I switch manually to WatchKit based they work fine. It would be helpful if Coffee Tracker code example (referenced in WWDC video and documentation) become updated with migration code.
3
4
3k
Aug ’23
watchOS 9: ClockKit-based complications occasionally failed to display
Hello! Two of my watch apps (HiCoffee and HiWater) occasionally have issues with complications not displaying properly on watchOS 9. I did NOT use the new WidgetKit to implement the complications, all the related code still uses the same previous ClockKit + SwiftUI. I have observed several different types of wrong behaviors. One specific complication cannot be displayed (rendered?), while others do work (from the same app). This indicates that my watch app is working properly. All complications on the face cannot be displayed. But the app logs indicates it's running properly. In addition, when you long press the face to edit complications, yet it can be displayed normally. Log shows CLKComplicationServer.sharedInstance().activeComplications always returns 0 no matter how many complications are added to the face. Also, the ComplicationController is NOT called by system. I'm not using WatchKit. This part of the code in my app has been working properly for a long time and has not been changed. But after the release of watchOS 9, I received a lot of feedback from users with this problem. So I think the problem is in watchOS 9. I haven't found a way to reproduce the problem yet. Any suggestions please?
7
2
2.8k
May ’23
Complication support in watch OS 9 with ClockKit
Hi Team, I am using the ClockKit to populate my watch app compilations. I have not added the WidgetKit target yet. As Apple start showing warnings for the storyboard in the watch extension, I replaced the storyboard with SwiftUI classes So now my app UI is created from SwiftUI and Complications are from ClockKit But when the watch is upgraded to 9, there are a few issues coming up related to complications most of them are actually related to the timeline and complications are becoming unresponsive So whether Apple still support ClockKit ? or is it mandatory to move to WidgetKIt?
0
0
887
May ’23
How do I get the user's location when generating timelines for a ClockKit complication?
I'm working on a widget in ClockKit (since WidgetKit is lacking in UI controls that I need for this app, namely the curved corner text). The widget will display data based on the user's location. It doesn't need to be completely precise, but it does need to update when the user moves about 10km or so. I tried setting up CLLocationManager to give a callback in the AppDelegate, but this doesn't seem to work on the clock face unless the location is set to Always, which doesn't seem to be allowed as it's being set to When in Use even with a call to requestAlwaysAuthorization. So, my main question is, what is the correct way to get the user's rough location in a complication? I know some of Apple's built-in complications do it -- namely, the sunrise/sunset complication.
1
0
1.3k
Jan ’23
Signing / Provisioning Profile Error After Enabling CloudKit + MusicKit Entitlements
Hi everyone, after enabling CloudKit in my project, my app started showing conflicts between MusicKit and CloudKit entitlements — and now Xcode is failing to generate the provisioning profile entirely. Current issue (Signing / Provisioning Profile Failure) Xcode shows this error: “Provisioning profile ‘iOS Team Provisioning Profile: team8.groovefy.dev’ doesn’t include the entitlements: com.apple.developer.media-library, com.apple.developer.music-user-token, com.apple.developer.musickit, com.apple.developer.playable-content, com.apple.security.exception.mach-lookup.global-name” Automatic signing fails, and Xcode cannot create or update the provisioning profile. This started right after CloudKit was enabled in the project. Context Before enabling CloudKit, MusicKit worked normally, including Apple Music authentication and playlist creation. After activating CloudKit capabilities: MusicKit stopped generating the Apple Music user token Playlist creation broke Now the provisioning profile cannot be rebuilt because the required MusicKit-related entitlements are no longer included Even after removing CloudKit entirely, the issue persists — as if the App ID or entitlements on the server side became inconsistent or corrupted. I already tried: Recreating App Identifier Recreating provisioning profiles Resetting capabilities Cleaning and reinitializing the Xcode project settings But Xcode still refuses to generate a valid provisioning profile that includes the MusicKit entitlements. Summary Enabling CloudKit caused MusicKit entitlements to collide, and now the provisioning profile no longer includes the required MusicKit entitlements — preventing the app from signing, running, or creating playlists. If anyone has faced this type of entitlements/provisioning corruption or knows how to reset the App ID entitlements on Apple’s side, any help would be greatly appreciated.
Replies
1
Boosts
0
Views
280
Activity
Dec ’25
Complex functions are not available
When I generate a dial through code, it prompts the following content: code: CLKWatchFaceLibrary * lib = [[CLKWatchFaceLibrary alloc] init]; [lib addWatchFaceAtURL:url completionHandler:^(NSError * _Nullable error) { }]; result: Complex functions are not available How to fix it? Make it usable, Thank you~
Replies
1
Boosts
0
Views
944
Activity
Dec ’24
ClockKit to WidgetKit migration bug
Hi, I'm migrating ClockKit complications to WidgetKit. Everything works well except when I run the WidgetKit version, I see complications appear twice each in the complications list for my app when adding them. If I restart the app from Xcode, it won't happen again, only for the first time. But on the actual device, only Watch restart or app reinstall fixes it which is frustrating and would not be ideal for live users. I even tried Apple's example ClockKit project -> added complications to watch face -> added WidgetKit target, CLKComplicationWidgetMigrator and func widgetConfiguration(from complicationDescriptor: CLKComplicationDescriptor) code -> run the app -> new complications appear correctly replacing old ones -> when hold to add/change complications I see it doubled (screenshot attached) and it's even selected twice If I add more complications, they will appear two times as well except one selected in two places almost like it's two same lists created. class ComplicationController: NSObject, CLKComplicationDataSource, CLKComplicationWidgetMigrator { @available(watchOSApplicationExtension 9.0, *) var widgetMigrator: CLKComplicationWidgetMigrator { self } @available(watchOSApplicationExtension 9.0, *) func widgetConfiguration(from complicationDescriptor: CLKComplicationDescriptor) async -> CLKComplicationWidgetMigrationConfiguration? { switch complicationDescriptor.identifier { case "Coffee_Tracker_Caffeine_Dose": return CLKComplicationStaticWidgetMigrationConfiguration( kind: "WidgetKitComplications", extensionBundleIdentifier: "com.example.apple-samplecode.Coffee-Tracker.watchkitapp.watchkitextension.WidgetKitComplications") default: return nil } }
Replies
4
Boosts
0
Views
953
Activity
Sep ’24
ClockKit Complications not working with Xcode 14 single-target watchOS app
I’ve created a single-target watchOS app in Xcode 14, but I can’t seem to get ClockKit complications working. I’ve added a CLKComplicationDataSource class to my watch target, and in the Info pane for my target I have set the CLKComplicationPrincipalClass key to MODULE-NAME.ComplicationController I haven’t yet added Complication placeholder images to my Assets.xcassets, but as far as I am aware, that shouldn’t be a problem while I am still testing. However, when I run it on a watchOS simulator, the complications never show up on the watch complications list when adding a complication. All of the tutorials I can find for ClockKit complications reference older two-target WatchKit apps. Do the newer single target apps no longer support ClockKit? If so, how can I make a two-target WatchKit app with Xcode 14? Unfortunately I cannot use WidgetKit for my complications because I need to support watchOS 7 at least, and WidgetKit only supports watchOS 9+ Thanks for your help
Replies
3
Boosts
1
Views
2.3k
Activity
Aug ’24
Will sharing watch faces and ClockKit be supported in watchOS 11?
Hi Apple Team, Am seeing that in Apple's "share watch face" documentation that ClockKit APIs are still being used to share watch faces. So my question is - will those ClockKit APIs (and therefore ClockKit complications) be supported in watchOS 11? Thank you.
Replies
1
Boosts
0
Views
778
Activity
Aug ’24
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 } } ...
Replies
2
Boosts
0
Views
1.4k
Activity
Jul ’24
Extract metadata from a .watchface
Hello, fellow developers! How would you approach .watchface file to extract it's metadata? I need to know in which version of the app the face was created, to prompt the user to update the app if necessary. Looking at binary I suppose that a .watchface file consists of a PNG previews and JSON metadata and it all packed in one file somehow. Probably archived with gzip.
Replies
0
Boosts
0
Views
678
Activity
Jul ’24
<decode: bad range for [%{public}s] got [offs:294 len:935 within:0]>
Suggestions on what is causing this? Where to look? Could it be related to having a CoreData 'abstract entity' that occurs in two configurations - one configuration for 'public' and one for 'private/shared'?
Replies
2
Boosts
0
Views
3.8k
Activity
Jul ’24
Major Clock app suggestion
When you use set an Alarm in clock app, you get to choose mutliple tones and even songs from Apple music. However, when you set a Sleep|Wake up alarm using a sleep schedule, you are prompted to choose only limited tones. This limits the Alarm tone options for sleep one. Hope, Apple lets users pick the full library of tones in next update.
Replies
1
Boosts
0
Views
707
Activity
Jun ’24
Complication works on watch, but not visible in watch app on phone
I have an iPhone app, and added watch support, including a simple launcher complication. I can add the complication using the edit UI on the watch, but the complication is not visible using the watch app on the iPhone. When I add my complication on the watch and then open the watch app on the iPhone, the complication slot shows as "Off". What could I be doing wrong?
Replies
2
Boosts
0
Views
892
Activity
Jun ’24
`WCSession.isComplicationEnabled` is `false` when complication is in Smart Stack
⌚️Hello, I've noticed in watchOS 10 that when a complication is in the Smart Stack, the value of WCSession.isComplicationEnabled is false. I'm not sure if this is intentional or a bug. It seems trivial at first glance, but it actually affects the communication mechanism mentioned in Implementing Two-Way Communication Using Watch Connectivity. In the following two scenarios, if the user has only added the app's complication to the Smart Stack, then the watch app will not be able to communicate properly with the iOS app. Scenario 1 - WCSession.transferCurrentComplicationUserInfo() // update complications from the iOS app if WCSession.default.isComplicationEnabled { let userInfoTransfer = WCSession.default.transferCurrentComplicationUserInfo(userInfo) // ... } As described in Implementing Two-Way Communication Using Watch Connectivity, when the iOS app proactively updates the data of the watch app, since WCSession.isComplicationEnabled is false, WCSession will refuse to transfer any data. This causes the standalone complication in Smart Stack to not be updated. Scenario 2 - WKApplicationRefreshBackgroundTask When the watch app uses WKApplication.scheduleBackgroundRefresh() to periodically update data, as long as the user has added the app's complication to the watch face, the corresponding WKApplicationRefreshBackgroundTask can be executed periodically in the background to fetch data. However, if the user has only added complication to the Smart Stack, then the watch app will be completely purged, and the background task will not be executed at all. Although WCSession.isComplicationEnabled is not directly used in this scenario, its behavior appears to be the same, that is, the complication in the Smart Stack is not considered a complication by the system. Should I submit a bug report?
Replies
2
Boosts
0
Views
1.3k
Activity
Feb ’24
Macbook Clock Widget Bug
Whenever I try to put my choice of time zones on the MacBook clock widget, it won't show on the main widget. It will show the stock clock options. Such as Cupertino, Tokyo, Sydney, and Paris, Even though I change them inside the app the widget won't display the changes.
Replies
1
Boosts
0
Views
815
Activity
Jan ’24
How can I re-create a CLKRelativeDateTextProvider in a WidgetKit complication?
I'm in the process of migrating one of my app's Apple Watch complications from ClockKit to WidgetKit. In my ClockKit complications, there are some cases where a show the relative time since the last event in the app (for example, "25MIN"). With ClockKit, this was quite straightforward using a CLKTextProvider designed for this exact purpose: CLKRelativeDateTextProvider(date: date, style: .offsetShort, units: [.hour, .minute]) This has always worked great, since it lets me specify that hours and minutes should be used, but not seconds, since they're not relevant here. How can I accomplish the same thing with WidgetKit and SwiftUI? The closest thing I've found is this: Text(date, style: .relative) It shows, for example: 14MIN 8SEC This is not what I want, since it shows seconds. It makes the complication look messy with all the extra information, and is distracting because it updates every second until an hour has passed. I suppose I could write my own logic to create a new timeline entry every minute to show the number of hours and minutes since the last update, but since CLKTextProvider works so nicely I wanted to check whether there is some way to accomplish the same thing without creating a new entry for every minute. There seem to be some more customizable options with date formatters, but I haven't found a way to combine this with the SwiftUI version that updates automatically on the Apple Watch face: https://developer.apple.com/documentation/foundation/date/relativeformatstyle/3766585-presentation
Replies
4
Boosts
0
Views
1.1k
Activity
Oct ’23
Userdefaults for complications are nil while watch is working fine
I'm able to successfully send userdefaults from the phone to the watch using applicationContext and save those userdefaults to the app group I created. For the watch, I see all the userdefaults come in successfully and I'm able to use them in the WatchOS app. Once I created the complications for the watch app, I am using the same app group ID and I added that app group in the capabilities of the watch extension but when I try to use the same userdefault that I'm using for the watch, everything is nil. I'm not understanding what I'm doing wrong. How do I share userdefaults between the watch and complication? This is how I'm bringing in the userdefaults from the phone to the watch let defaults = UserDefaults(suiteName: K.appGroupID) if let value1 = applicationContext["lat"] as? Double { defaults?.setValue(value1, forKey: "lat") } if let value2 = applicationContext["lng"] as? Double { defaults?.setValue(value2, forKey: "lng") } ... I am able to use this exact function in the watch app, but in the complication, the userdefault is nil. let formatter = DateFormatter() formatter.timeStyle = .short formatter.timeZone = .current let defaultLoad = UserDefaults.init(suiteName: K.appGroupID) if defaultLoad!.bool(forKey: "timeFormat") == true { ... I tried to remove and re-add the app group but that didn't work either. I also created a separate app group for the watch and extension to use alone but still same issue.
Replies
4
Boosts
1
Views
2.2k
Activity
Aug ’23
Bluetooth ANCS don't send ringing alarm clock and countdown timer
Hello everyone, sorry for my ignorance about it, with ANCS I managed to get all the notifications except the alarm that rings and the timer expired, where am I wrong? do they travel on other channels like gatt? if yes can someone help me understand how to receive these 2 information? the alarm goes off and the timer expired? Thanks in advance to everyone who will help me, Marco.
Replies
1
Boosts
0
Views
1.3k
Activity
Aug ’23
Migrating ClockKit complications to WidgetKit not working
I've implemented delegate method suggested in the article https://developer.apple.com/documentation/widgetkit/converting-a-clockkit-app and double (even triple) checked kind and extensionBundleIdentifier of my StaticConfiguration But when I install the app version containing WidgetKit complications they don't replace old ones from ClockKit on the watch face. In the same time old complications are not displayed - I see empty slots. When I check setup in Watch app on the phone I see that old complications remain assigned. If I switch manually to WatchKit based they work fine. It would be helpful if Coffee Tracker code example (referenced in WWDC video and documentation) become updated with migration code.
Replies
3
Boosts
4
Views
3k
Activity
Aug ’23
When will ClockKit completely stop working?
Hello Community! We have an Apple Watch app that intensively uses ClockKit complication API. As to the release of WatchOS 10, ClockKit has been deprecated. The question is what time do developers have to make complete transition to WidgetKit? How long WatchOS will support ClockKit complications?
Replies
2
Boosts
1
Views
1k
Activity
Jul ’23
watchOS 9: ClockKit-based complications occasionally failed to display
Hello! Two of my watch apps (HiCoffee and HiWater) occasionally have issues with complications not displaying properly on watchOS 9. I did NOT use the new WidgetKit to implement the complications, all the related code still uses the same previous ClockKit + SwiftUI. I have observed several different types of wrong behaviors. One specific complication cannot be displayed (rendered?), while others do work (from the same app). This indicates that my watch app is working properly. All complications on the face cannot be displayed. But the app logs indicates it's running properly. In addition, when you long press the face to edit complications, yet it can be displayed normally. Log shows CLKComplicationServer.sharedInstance().activeComplications always returns 0 no matter how many complications are added to the face. Also, the ComplicationController is NOT called by system. I'm not using WatchKit. This part of the code in my app has been working properly for a long time and has not been changed. But after the release of watchOS 9, I received a lot of feedback from users with this problem. So I think the problem is in watchOS 9. I haven't found a way to reproduce the problem yet. Any suggestions please?
Replies
7
Boosts
2
Views
2.8k
Activity
May ’23
Complication support in watch OS 9 with ClockKit
Hi Team, I am using the ClockKit to populate my watch app compilations. I have not added the WidgetKit target yet. As Apple start showing warnings for the storyboard in the watch extension, I replaced the storyboard with SwiftUI classes So now my app UI is created from SwiftUI and Complications are from ClockKit But when the watch is upgraded to 9, there are a few issues coming up related to complications most of them are actually related to the timeline and complications are becoming unresponsive So whether Apple still support ClockKit ? or is it mandatory to move to WidgetKIt?
Replies
0
Boosts
0
Views
887
Activity
May ’23
How do I get the user's location when generating timelines for a ClockKit complication?
I'm working on a widget in ClockKit (since WidgetKit is lacking in UI controls that I need for this app, namely the curved corner text). The widget will display data based on the user's location. It doesn't need to be completely precise, but it does need to update when the user moves about 10km or so. I tried setting up CLLocationManager to give a callback in the AppDelegate, but this doesn't seem to work on the clock face unless the location is set to Always, which doesn't seem to be allowed as it's being set to When in Use even with a call to requestAlwaysAuthorization. So, my main question is, what is the correct way to get the user's rough location in a complication? I know some of Apple's built-in complications do it -- namely, the sunrise/sunset complication.
Replies
1
Boosts
0
Views
1.3k
Activity
Jan ’23