Please note, this question is regarding Xcode 15 beta 4, iOS 17 beta 3, and watchOS 10 beta 3
I have a watchOS 10 App with iOS 17 companion app with two Widget (WidgetKit) Extension Targets. Both targets share the same codebase where each Swift file has both targets set in the Target Membership settings.
Some parts of my code are behind #if os(watchOS)
compiler directives, for example when setting the supported widget families:
#if os(watchOS)
.supportedFamilies([.accessoryCircular, .accessoryRectangular])
#else
.supportedFamilies([.accessoryCircular, .systemSmall, .systemMedium])
#endif
I got multiple Widgets that are made available through a WidgetBundle
. However, the following issues also exist when there is only one widget.
This is my current WidgetBundle
and preview code:
@main
struct WidgetExtensionBundle: WidgetBundle {
var body: some Widget {
StaticSampleWidget()
if #available(iOSApplicationExtension 17.0, *) {
AppIntentSampleWidget()
}
}
}
#if os(watchOS)
#Preview(as: .accessoryRectangular) {
StaticSampleWidget()
} timeline: {
StaticSampleWidget_Entry(date: .now, emoji: "😀")
StaticSampleWidget_Entry(date: .now, emoji: "🤩")
}
#else
#Preview(as: .systemSmall) {
StaticSampleWidget()
} timeline: {
StaticSampleWidget_Entry(date: .now, emoji: "😀")
StaticSampleWidget_Entry(date: .now, emoji: "🤩")
}
#endif
When I try to use the preview in Xcode, it cannot build the app and show no previews. By trying different settings and combinations of selected targets, I sometimes get at least the iOS preview running, but never the watchOS preview. Also, the first #Preview
behind the #if os(watchOS)
is grayed out. On the Canvas it always shows two Preview tabs, even though it should only be one depending on the selected target. I sometimes get the following errors, and sometimes it doesn’t tell me at all what is wrong:
Sample.watchkitapp.WidgetExtensionWatch.appex
with id xxx.xxx.Watch-
Sample.watchkitapp.WidgetExtensionWatch does not define either an NSExtensionMainStoryboard or
NSExtensionPrincipalClass key with a string value
Failed to build WidgetExtensionBundle.swift
How do I correctly setup my targets, and preview code to be able to show the relevant previews for iOS and watchOS?
2
Answers
After several trials and errors, I figured out the issues I had. I'll explain step by step what I've done to get it running in my case. Please note, there might be certain settings that could still prevent the preview from working, but this worked for me. Also, the iOS/watchOS and Xcode versions are still in Beta. Things might change and not work the same after a future release.
First I confirmed the following settings:
The watchOS Widget Target is added as a dependency in the watchOS target The iOS Widget Target is added as a dependency in the iOS app
The watchOS Widget Target is set to support only watchOS as a
destination The iOS Widget Target is set to support iOS and iPad as a destination
And in the
Build Settings
, the supported Platform match those too.In the watchOS Widget target
Build Settings
I also setApp is Available Only on Apple Watch
toYes
Two
Info.plist
andInfo-Watch.plist
files are set individually in each target'sBuild Settings
underPackaging > Info.plist File
There are four build schemes, one for each target.
Under
Manage Run Destinations > Simulators
I ensured the Apple Watch was also set toalways show as run destination
.Most importantly I changed the preview code to the following:
I think this might be a bug with the new Swift macros. But by putting macros and the compiler directive separate, nothing was grayed out anymore and only one preview tab was shown.
Next, I did run each target in the simulator (iOS App, watchOS App, iOS Widget, watchOS Widget) and made sure everything did build for the simulator.
Note, when running and debugging the extensions, only one
Widget
can be inside theWidgetBundle
, all the others need to be commented out while running the extension in the simulatorI selected either the watchOS or iOS Widget extension scheme.
I made sure the preview canvas has also the correct device type selected(!)
And finally, the preview was working with the correct device.
For me, previews don’t work. But, it is probably bug from Apple which is officially documented in Xcode 15 Beta 8 release notes