Yurkevich
Yurkevich

Reputation: 4517

Complication not appears in Gallery

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.

Xcode Complication Configuration

Troubleshooting.

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

Answers (3)

Ahmadreza
Ahmadreza

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

Yurkevich
Yurkevich

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

Mike Welsh
Mike Welsh

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

Related Questions