Reputation: 4517
I have simple complication for launching my app from the Watch Face. It doesn't show any data, just displays an image. I followed Adding Complications to the Gallery guide but I wasn't able to add my complication to the Complications Gallery on in iPhone Watch app.
public func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
guard let tempalte = buildTemplate(for: complication) else {
fatalError("Unsuported Complication Family.")
}
handler(tempalte)
}
// Helper function to build template.
fileprivate func buildTemplate(for complication: CLKComplication) -> CLKComplicationTemplate? {
let textProvider = CLKSimpleTextProvider.localizableTextProvider(withStringsFileTextKey: "Caffeine")
switch complication.family {
case .modularSmall:
let icon = #imageLiteral(resourceName: "Complication/Modular")
let complicationTemplate = CLKComplicationTemplateModularSmallSimpleImage()
complicationTemplate.imageProvider = CLKImageProvider(onePieceImage: icon)
return complicationTemplate
case .circularSmall:
let icon = #imageLiteral(resourceName: "Complication/Circular")
let complicationTemplate = CLKComplicationTemplateCircularSmallSimpleImage()
complicationTemplate.imageProvider = CLKImageProvider(onePieceImage: icon)
return complicationTemplate
case .utilitarianSmall:
let icon = #imageLiteral(resourceName: "Complication/Utilitarian")
let complicationTemplate = CLKComplicationTemplateUtilitarianSmallSquare()
complicationTemplate.imageProvider = CLKImageProvider(onePieceImage: icon)
return complicationTemplate
case .utilitarianLarge:
let icon = #imageLiteral(resourceName: "Complication/Utilitarian")
let complicationTemplate = CLKComplicationTemplateUtilitarianLargeFlat()
complicationTemplate.imageProvider = CLKImageProvider(onePieceImage: icon)
complicationTemplate.textProvider = textProvider
return complicationTemplate
case .utilitarianSmallFlat:
let icon = #imageLiteral(resourceName: "Complication/Utilitarian")
let complicationTemplate = CLKComplicationTemplateUtilitarianSmallFlat()
complicationTemplate.imageProvider = CLKImageProvider(onePieceImage: icon)
complicationTemplate.textProvider = textProvider
return complicationTemplate
case .extraLarge:
let icon = #imageLiteral(resourceName: "Complication/Extra Large")
let complicationTemplate = CLKComplicationTemplateExtraLargeSimpleImage()
complicationTemplate.imageProvider = CLKImageProvider(onePieceImage: icon)
return complicationTemplate
default:
return nil
}
}
complicationManifest.json file.
{
"supported complication families" : {
"3" : "B82ADE2C-045D-491D-87DD-C24148804480.json",
"6" : "A332202A-4B7B-49E0-83FB-DB398089E4FE.json",
"4" : "817476CB-1683-4604-A76D-2977236448AD.json",
"2" : "50AB27ED-0FA3-41AD-A3E7-CC9C62E48D82.json",
"0" : "DBE31877-7BB0-4671-B065-6FE00333929E.json",
"7" : "96966B70-AB8D-4DB3-AB64-AFDF1F09EB88.json"
},
"client ID" : "net.borisy.ProductDisplayName.watchkitapp.watchkitextension"
}
Project Settings.
Troubleshooting.
gallery.ckcomplication
gallery.ckcomplication
located in the project at root level. Same level as .xcodeproj
.Update.
I've added more code. I've also added ckcomplication.strings
to the Watch Extension Target.
Reading Apple guide again and following line got me thinking:
For example, MyBundleName.ckcomplication.
Maybe we suppose to rename generated folder name gallery with the bundle name. I've tried to do it. No luck so far.
Upvotes: 1
Views: 1679
Reputation: 7222
In my case in 2020, the complications were fine on watchOS7, but my app also supported WatchOS5 but the complications were not there so I added this to watch extension info.plist file:
<key>CLKComplicationPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ComplicationController</string>
<key>CLKComplicationSupportedFamilies</key>
<array>
<string>CLKComplicationFamilyModularSmall</string>
<string>CLKComplicationFamilyModularLarge</string>
<string>CLKComplicationFamilyUtilitarianSmall</string>
<string>CLKComplicationFamilyUtilitarianSmallFlat</string>
<string>CLKComplicationFamilyUtilitarianLarge</string>
<string>CLKComplicationFamilyCircularSmall</string>
<string>CLKComplicationFamilyExtraLarge</string>
</array>
Upvotes: 0
Reputation: 4517
I watch this video again and noticed ComplicationController
has prefix $(PRODUCT_MODULE_NAME)
in the target preferences:
My project didn't had this prefix, I quickly found out that ComplicationController methods never called. Because that was the place when we set tintColor
, default complication was displayed.
I solved this by deleting my watch app and watch extension targets and creating new from scratch. The prefix appeared in Xcode and I could see my app icon in Complications Gallery running in Simulator.
Upvotes: 1
Reputation: 808
I'm not sure what the rest of your method looks like, but I had the same problem until I made sure I added enough information for all complication types we support. It then generated the appropriate json and image files.
Seems silly to have a blank text provider (and the template image matches the complication image set), but it seems to be a workaround.
- (void)getLocalizableSampleTemplateForComplication:(CLKComplication *)complication
withHandler:(void(^)(CLKComplicationTemplate *complicationTemplate))handler {
// This method will be called once per supported complication,
// and the results will be cached
UIImage *templateImage = [UIImage imageNamed:@"template"];
CLKImageProvider *image =
[CLKImageProvider imageProviderWithOnePieceImage:templateImage];
CLKTextProvider *text = [CLKTextProvider textProviderWithFormat:@""];
CLKComplicationTemplate *complicationTemplate;
switch (complication.family) {
case CLKComplicationFamilyCircularSmall: {
CLKComplicationTemplateCircularSmallSimpleImage *small =
[[CLKComplicationTemplateCircularSmallSimpleImage alloc] init];
small.imageProvider = image;
complicationTemplate = small;
break;
}
case CLKComplicationFamilyExtraLarge: {
CLKComplicationTemplateExtraLargeSimpleImage *large =
[[CLKComplicationTemplateExtraLargeSimpleImage alloc] init];
large.imageProvider = image;
complicationTemplate = large;
break;
}
case CLKComplicationFamilyModularLarge: {
// Unexpected complication type.
break;
}
case CLKComplicationFamilyModularSmall: {
CLKComplicationTemplateModularSmallSimpleImage *small =
[[CLKComplicationTemplateModularSmallSimpleImage alloc] init];
small.imageProvider = image;
complicationTemplate = small;
break;
}
case CLKComplicationFamilyUtilitarianLarge: {
CLKComplicationTemplateUtilitarianLargeFlat *large =
[[CLKComplicationTemplateUtilitarianLargeFlat alloc] init];
large.imageProvider = image;
large.textProvider = text;
complicationTemplate = large;
break;
}
case CLKComplicationFamilyUtilitarianSmall: {
CLKComplicationTemplateUtilitarianSmallSquare *small =
[[CLKComplicationTemplateUtilitarianSmallSquare alloc] init];
small.imageProvider = image;
complicationTemplate = small;
break;
}
case CLKComplicationFamilyUtilitarianSmallFlat: {
CLKComplicationTemplateUtilitarianSmallFlat *small =
[[CLKComplicationTemplateUtilitarianSmallFlat alloc] init];
small.imageProvider = image;
small.textProvider = text;
complicationTemplate = small;
break;
}
}
handler(complicationTemplate);
}
It's hacky and I think the proper solution is to provide real image (and text) data, but this seems to work.
Upvotes: 3