WatchOS 5 – Adding a simple complication to launch the app in Objective-C

I was trying to add some complications to launch my watch app, Departure Board, and I couldn’t find any decent tutorial for how to do it.

Starting point:

  • iOS App
  • WatchOS App
  • Objective-C

Create a Data Source Class

Create a Cocoa Touch subclass of NSObject that complies with CLKComplicationDataSource.

  • File > New > New File…
  • Cocoa Touch Class
  • Give it a name
  • Subclass of NSObject
  • Make sure the .m has a target membership with Watch App Extension
  • Add <CLKComplicationDataSource> after : NSObject to denote that this class complies with the protocol.

Implement Data Source Class

I implemented the following methods:

- (void)getCurrentTimelineEntryForComplication:(nonnull CLKComplication *)complication withHandler:(nonnull void (^)(CLKComplicationTimelineEntry * _Nullable))handler

This method is called and your class should call the handler with a CLKComplicationTimelineEntry for the (nonnull CLKComplication *)complication that was passed to the Data Source.

- (void)getSupportedTimeTravelDirectionsForComplication:(nonnull CLKComplication *)complication withHandler:(nonnull void (^)(CLKComplicationTimeTravelDirections))handler

This method is called and your class should return that supported time travel directions.

-(void)getPlaceholderTemplateForComplication:(CLKComplication *)complication withHandler:(void (^)(CLKComplicationTemplate * _Nullable))handler

This is called once per complication type to get a template for the complication to show in the complication picker menus – the result is cached.

Examples

- (void)getCurrentTimelineEntryForComplication:(nonnull CLKComplication *)complication withHandler:(nonnull void (^)(CLKComplicationTimelineEntry * _Nullable))handler {
    switch (complication.family) {
        case CLKComplicationFamilyGraphicBezel: {
            CLKComplicationTemplateGraphicBezelCircularText * myComplicationTemplate = [[CLKComplicationTemplateGraphicBezelCircularText alloc] init];
            CLKComplicationTemplateGraphicCircularImage* myCircComplicationTemplate = [CLKComplicationTemplateGraphicCircularImage new];
            // Create your template object
            myCircComplicationTemplate.imageProvider = [CLKFullColorImageProvider providerWithFullColorImage:[UIImage imageNamed:@"complicationImageW"]];
            // Create your template object
            myComplicationTemplate.circularTemplate = myCircComplicationTemplate;
            myComplicationTemplate.textProvider = [CLKTextProvider textProviderWithFormat:@"Departure Board"];
            handler([CLKComplicationTimelineEntry entryWithDate:[NSDate date] complicationTemplate:myComplicationTemplate]);
            break;
        }
        case CLKComplicationFamilyUtilitarianLarge: {
            CLKComplicationTemplateUtilitarianLargeFlat * myComplicationTemplate = [CLKComplicationTemplateUtilitarianLargeFlat new];
            // Create your template object
            myComplicationTemplate.textProvider = [CLKTextProvider textProviderWithFormat:@"Departure Board"];
            handler([CLKComplicationTimelineEntry entryWithDate:[NSDate date] complicationTemplate:myComplicationTemplate]);
            break;
        }
        case CLKComplicationFamilyGraphicCircular: {
            CLKComplicationTemplateGraphicCircularImage* myComplicationTemplate = [CLKComplicationTemplateGraphicCircularImage new];
            // Create your template object
            myComplicationTemplate.imageProvider = [CLKFullColorImageProvider providerWithFullColorImage:[UIImage imageNamed:@"complicationImageW"]];
            handler([CLKComplicationTimelineEntry entryWithDate:[NSDate date] complicationTemplate:myComplicationTemplate]);
            break;
        }
        default:
            break;
    }
}
- (void)getSupportedTimeTravelDirectionsForComplication:(nonnull CLKComplication *)complication withHandler:(nonnull void (^)(CLKComplicationTimeTravelDirections))handler {
    handler(CLKComplicationTimeTravelDirectionNone);
}
-(void)getPlaceholderTemplateForComplication:(CLKComplication *)complication withHandler:(void (^)(CLKComplicationTemplate * _Nullable))handler{
    switch (complication.family) {
        case CLKComplicationFamilyGraphicBezel: {
            CLKComplicationTemplateGraphicBezelCircularText * myComplicationTemplate = [[CLKComplicationTemplateGraphicBezelCircularText alloc] init];
            CLKComplicationTemplateGraphicCircularImage* myCircComplicationTemplate = [CLKComplicationTemplateGraphicCircularImage new];
            // Create your template object
            myCircComplicationTemplate.imageProvider = [CLKFullColorImageProvider providerWithFullColorImage:[UIImage imageNamed:@"complicationImageW"]];
            // Create your template object
            myComplicationTemplate.circularTemplate = myCircComplicationTemplate;
            myComplicationTemplate.textProvider = [CLKTextProvider textProviderWithFormat:@"Departure Board"];
            handler(myComplicationTemplate);
            break;
        }
        case CLKComplicationFamilyUtilitarianLarge: {
            CLKComplicationTemplateUtilitarianLargeFlat * myComplicationTemplate = [CLKComplicationTemplateUtilitarianLargeFlat new];
            // Create your template object
            myComplicationTemplate.textProvider = [CLKTextProvider textProviderWithFormat:@"Departure Board"];
            handler(myComplicationTemplate);
            break;
        }
        case CLKComplicationFamilyGraphicCircular: {
            CLKComplicationTemplateGraphicCircularImage* myComplicationTemplate = [CLKComplicationTemplateGraphicCircularImage new];
            // Create your template object
            myComplicationTemplate.imageProvider = [CLKFullColorImageProvider providerWithFullColorImage:[UIImage imageNamed:@"complicationImageW"]];
            handler(myComplicationTemplate);
            break;
        }
        default:
            break;
    }
}

In these examples, complicationImageW is a PDF in an xcasset. This allows the watch to scale a single image to the required size.

Configure Watch App

In the Project Settings screen select the Watch App Extension, then the supported families of complications you want from the Complications Configuration.

Set the name of the Data Source Class name.

Build and Run and it should work!

I threw this post together quite quickly, as I couldn’t find good objective-c code for this task. If anything is missing or misleading, let me know, @DannyBres.

Leave a Reply

Your email address will not be published.