I'm seeing problems with the new Apple Watch Modular Ultra Watch face...
This is all using the latest WatchOS 10.1 and with WidgetKit complications. (Have also tested with the new WatchOS 10.2 beta in the simulator)
The Graphic Circular (accessoryCircular) complications space the numbers differently sometimes causing maximum and minimum numbers to look like one long number (see small circular complications in screenshot)
The exact same complication in the accessoryRectangular on the Modular Ultra face clips text when it doesn't on any other watch face
I've filed feedback FB13344580
Hopefully the screenshots show the issue well.
Watch Complications
RSS for tagDisplay timely and relevant information about your app on the Apple Watch face using Complications.
Posts under Watch Complications tag
46 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I am trying to add Widget Complications to an existing Apple Watch app. I added the WatchOS widgets extension and followed instructions to create static, non-updating complications to merely launch the app from the watch home screen.
Here is my code in the widget extension:
import WidgetKit
import SwiftUI
struct Provider: TimelineProvider {
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
}
func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
}
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date())
}
func snapshot(in context: Context) async -> SimpleEntry {
SimpleEntry(date: Date())
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
}
struct TrapScores_WidgetsEntryView : View {
@Environment(\.widgetFamily) var widgetFamily
var entry: Provider.Entry
var body: some View {
switch widgetFamily {
case .accessoryCorner:
ComplicationCorner()
case .accessoryCircular:
ComplicationCircular()
case .accessoryRectangular:
Text("TrapScores")
case .accessoryInline:
Text("TrapScores")
@unknown default:
//mandatory as there are more widget families as in lockscreen widgets etc
Text("AppIcon")
}
}
}
@main
struct TrapScores_Widgets: Widget {
let kind: String = "TrapScores_Complications"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
TrapScores_WidgetsEntryView(entry: entry)
.containerBackground(.fill.secondary, for: .widget)
}
.configurationDisplayName("TrapScores")
.description("This will launch TrapScores App")
.supportedFamilies([.accessoryCorner, .accessoryCircular])
}
}
struct ComplicationCircular: View {
var body: some View {
Image("Graphic Circular")
.widgetAccentable(true)
.unredacted()
}
}
struct ComplicationCorner: View {
var body: some View {
Image("Graphic Circular")
.widgetAccentable(true)
.unredacted()
}
}
#Preview(as: .accessoryCircular) {
TrapScores_Widgets()
} timeline: {
SimpleEntry(date: .now)
}
The complications appear fine in the preview:
The complication can be added to the watch face, but no graphic comes with it and it is a blank circle:
Any suggestions on what I'm doing wrong?
2 years ago using Xcode 13, I created a phone app with a companion Watch app and it worked fine. This past month using Xcode 15, I created a new phone and companion app and everything is working with the following exception.
From Xcode, my new app installs on the phone and watch, but my Watch app doesn't show up in the list of apps you can use as a launch complication on one of your watch faces.
The app does show up in the launch screen for apps installed on the watch, so I assume the watch icon is generated properly. I started out using a single 1024x1024 app icon so I thought maybe I needed to create all variations of the icon before I'd see them as a complication option. I created all variations and loaded them in the Appicon asset. Still no luck.
the one major difference between my Xcode 13 and Xcode 15 projects is the 15 project includes one watch app, where the 13 project includes the watch app and a WatchKit extension. my understanding is Xcode 14 and 15 don't use WatchKit Extension.
So... what do I need to do to be able to add my Xcode 15 watch app icon to a watch face so I can launch the app from there?
I'm developing my app for WatchOS 10 with Xcode 15.0.1.
I'm trying to make a complication with WidgetKit (SwiftUI) to make it easier the user to launch the app. I'm using a simple and small image 50x50px to test it first.
But when I try to add to the Watch Face, it show a gray circle like there is nothing there. But when i'm editing the Watch Face it show the image :/, like the image bellow:
And another problem is when is Accent mode, it fills the image with a gray color, as the image above shows it.
I tryed to add monochrome png image with the alpha-channel, but even that didn't worked too.
And my code is simpler has that:
var body: some View {
Image("Cat")
}
Someone is facing this same problem? Has any possible solution.
Just finalising some work on my app update, and it seems that when you go to select an item to show in a complication, when you select your app in the list, the subsequent list only shows 15 of your items.
If a user of my app has transferred 20 items to their Watch, they can't select five of them to be shown in a complication. Is that right?
If that's a hard limit then I need to be able to separate them out into bunches of 15 items, or maybe have them display under A-E, F-J etc.
Does this have to be done as a separate Widget in the WidgetBundle? And how do I do that? Given that I currently have one widget in that bundle that should show everything (20 items), how would I split it out to show an "A-E" widget with those items beginning with A...E? Do I have to have an A-E widget with its own set of data?
I'm trying to find the best way to reload my Widgets and Complications.
My App tries to show the current status vehicles. It gets the data using an API. And you don't know when this status changes. So I need to know when it makes sense to reload the widgets and complications.
Here is a quote from the documentation:
A widget’s budget applies to a 24-hour period. WidgetKit tunes the 24-hour window to the user’s daily usage pattern, which means the daily budget doesn’t necessarily reset at exactly midnight. For a widget the user frequently views, a daily budget typically includes from 40 to 70 refreshes. This rate roughly translates to widget reloads every 15 to 60 minutes, but it’s common for these intervals to vary due to the many factors involved.
This is by far the worst "definition" if ever seen :(
There is a 24 period, but you don't know when it starts and you don't know how much max refreshes you have and you also don't know how many refreshes you have left.
How should someone develop a good solution with such a "definition"?
So, I would like to know how you handle this?
Perhaps a Apple engineer could light me up here :)
Prior to watchOS10, I marked a view that I want to hide sensitive information when not being worn by using .privacySensitive() This had been working just fine.
Comes watchOS10, this doesn't work anymore. Even with this simple code
Text("TEST Privacy")
.containerBackground(for: .widget) {
Color.black
}
.privacySensitive()
The text view is displayed even when not being worn.
Has anyone experienced this? It seems like a bug to me. Any workaround? Thank you.
Current project structure:
Main iOS app (targets iOS 17).
Widget Extension (targets iOS 17).
Watch app (targets watchOS 10).
Complications Extension (a Widget Extension, targets watchOS 10).
I did have the complications embedded within the Watch app, but you cannot have two @mains in the same target so the complications are in their own WidgetKit extension.
Sadly, when you add a WidgetKit extension to your project, Xcode ALWAYS sets it as an iOS widget extension; it doesn't give you the choice to make it a watchOS extension so you have to figure it out yourself.
Now, I'm hitting an issue where the main iOS app works fine, the iOS widgets work fine, the Watch app runs fine, but the complications dot show up anywhere. I can't preview them in Xcode because it says various things like:
This app was not built to support this device family; app is compatible with (
1,2
) but this device supports (
4
}
I can't find any information on what goes where in the build settings.
Can someone tell me how each bit of the project should look in the build settings, please?
(There's no information anywhere in Apple's developer documentation - which is a bit weird. They've released Xcode and they have no information on the various bits. And why doesn't Xcode set up a WidgetKit extension properly when you add it? Must we all do this manually, Apple?)
I have a watch extension app that is used to show the complications using ClockKit. Then when we upgraded to watch OS 9, I added the WidgetKit Extension and all migration code for clockKit as well. Everything was working fine in Watch OS 9
But now when we upgraded to watch OS 10. The widgetKit based complication not at all running, I can't even see any of our complication in watch face
On top of that the WidgetKit extension is not showing any debug information as well, none of the break points are executed
Please let me know if anyone knows the issue
The modular ultra watchface ignores the font type I set in my complication.
Happens in simulator and on device (see screenshots).
I set the font via:
.font(.system(size: CGFloat(self.fontSize), weight: self.fontWeight, design: .monospaced))
Can you please help? Is this as designed or a bug?
I really a monospaced font in that place.
Thanks!
Correct:
Wrong:
I just got my new Apple Watch series 9 - woo!
But I loaded a couple of my test apps onto it - and the complications are not rendering.
They work fine on my "old" series 6 (both are on WatchOS 10).
I tried resizing them. They run and render fine in the simulator.
But this is how it looks on my actual watch (the upper 2 complications are mine).
In my Watch app on watchOS 9 I was using .foregroundColor(myColour) to colour the text in a widgetLabel on a corner complication like this:
let myColour: Color = functionThatReturnsAColorObjectConstructedLike Color.init(...) // green
.widgetLabel {
Text(myText)
.foregroundColor(myColour)
}
It worked fine; the widget label was green.
Now, in watchOS 10, I see that foregroundColor() is being deprecated in favour of foregroundStyle(), and I can use .foregroundStyle(.green), and - importantly - foregroundStyle() is only available on watchOS 10 and newer.
myColour is calculated depending on some other info, so I can't just write .green, and when I use .foregroundStyle(myColour) the widget label comes out as white every time, even if I set myColour = .green.
I think I have to use some sort of extension to pick the right combination, something like:
extension View {
func foregroundType(colour: Colour, style: any ShapeStyle) -> some THING? {
if #available(watchOS 10.0, *) {
return foregroundStyle(style)
} else {
return foregroundColor(colour)
}
}
}
// Usage
let myStyle: any ShapeStyle = SOMETHING?
...
.widgetLabel {
Text(myText)
.foregroundType(colour: myColour, style: myStyle)
It doesn't work. I just can't figure out what should be returned, nor how to return it. Any ideas?
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
Hi guys,
We have received several reports from our users: after deleting the watch app, the complications still remain.
It seems system cache the config and forget to remove after deleting the app.
(Our app is useing WidgetKit as complications)
I've migrated my ClockKit complication to WidgetKit in my app.
Everything is working fine when I run the app on watch OS 9.4 simulator with Xcode 14.3.1
But when I compile withe Xcode 15 Beta 8 ( or beta 7, 6..), the invalidateConfigurationRecommendations() does not work anymore.
the Recommendations() func from the IntentTimelineProvider is not called and thus the complication/widget list is not updated for the user
The rest is working fine, all widgets are well displayed, and I can still add / change any widget from the original list.
Running the app on a watchOS 10 simulator using Xcode 14.3.1, I've succeeded to see an error message :
[widget] invalidateConfigurationRecommendations() - error reloading supported intents: Process not authorized to make this timeline request
But I could not find any information about this error
I've also tried by migrating the SiriIntent to AppIntent on Xcode 15 Beta 8, but the issue persists, Recommendations() is still not called upon invalidateConfigurationRecommendations()
The application project is composed of :
iOS App
watchKit App
WatchKit Extension
Widget Extension (for IOS App)
Widget Intent (for iOS App)
Complication Extension (for watchOS widgets)
Looking desperately how to fix this...
Thanks for any help
We are migrating ClockKit complications to WidgetKit in our watch app (watchOS 9+). The migration went smoothly, UI part works just fine. However, we've hit the wall with widgets not updating when requested by the watch app. I believe we are missing something very simple and fundamental, but couldn't find what exactly so far. Advice and tips would be very welcome! 🙇♂️
Our implementation details:
Whenever data is changed in the main app, the updated data is submitted to the watch app via WatchConnectivity framework using WCSession.default.transferCurrentComplicationUserInfo(_:). According to documentation, this method should be used to transfer complication-related data, since it will wake the watch app even if it is in the background or not opened at all.
Watch app receives updated data and stores it in UserDefaults shared with Watch Widget Extension hosting WidgetKit complications via App Group.
Watch app then request widget timeline reload via WidgetCenter.shared.reloadAllTimelines(). According to documentation, it reloads the timelines for all configured widgets belonging to the containing app, so it seems the appropriate way to reload WidgetKit complications.
Widget Timeline Provider class in Watch Widget Extension reads updated data from shared UserDefaults and uses it to provide the updated snapshot for widget views to render.
We believe our implementation logic is correct, but it doesn't work, for some reason. Widgets sometimes update when the watch app is opened, but not always. The most definitive way to force widgets to update is to switch to a different watch face, which confirms that the Widget Timeline Provider has access to properly updated data.
P.S. We are aware of the daily reload budget imposed on widgets, so we use widgets reload trigger sparingly. Anyway, according to documentation, reload budget is not effective when in DEBUG mode, but widgets won't reload even in DEBUG mode.
Thank you!
In my watch app the AppIntentRecommendation that is returned by func recommendations() needs to be updated after the app is launched.
Problem:
The information that I need to return a list of AppIntentRecommendation is not available when the app is first installed, so I return a "dummy" AppIntentRecommendation initially.
After the app is launched for the first time and user has signed in, I can update the AppIntentRecommendation in func recommendations() but watchOS does not update the list of widgets presented as complications.
func recommendations() -> [AppIntentRecommendation<ConfigurationAppIntent>] {
// Create an array with all the preconfigured widgets to show.
let defaults = UserDefaults.init(suiteName: "group.myApp")!
guard let names = defaults.dictionary(forKey: "names" as? [String:String] else {
return [AppIntentRecommendation(intent: .Demo, description: "Demo")]
}
var recs = [AppIntentRecommendation<ConfigurationAppIntent>]()
for (idx, name) in names() {
let rec = ConfigurationAppIntent()
rec.order = idx
rec.carName = name
rec.action = nil
recs.append(AppIntentRecommendation(intent: rec, description: "name") )
}
return recs
}
}
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?
I have a watch complication that used to work just fine and now all of a sudden in my latest build it's showing only dashes. The watch app is there, if I tap on the complication then the watch app opens correctly, if I edit the watch face and select the complication I can see my placeholder (and it's fine) but when I select that complication, the sample watch face shows dashes.
The only major change I've made is to make the watch app a single-target without an extension delegate as per Apple's recommended settings. I don't think this is the problem as the simulator shows the complication. It's only on the Watch Series 4 that I'm testing on that I can't see my complication.
It was working only last week and I have not touched the complication code at all, so I'm stumped as to what's wrong. I can't find any help on line, apparently no one has ever seen the complication just have dashes.
When I debug the watch app and ask for how many complications there are, it comes back with zero even though I've put them on the watch face. It seems like watchOS9 is just not respecting the complication any longer but I can't figure out why.
Please note that I'm not using WidgetKit complications as the corner complication doesn't flow the text in an arc like ClockKit does, so I'm still using the old complications. But none of the code is getting called as none of my breakpoints are firing.
I've rebooted the watch about 10 times and the problem persists.
Any ideas why all of a sudden this has fallen over and gone boom?
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