Search code examples
watchkitapple-watch-complicationclockkit

Composing Text Providers with CLKTextProvider.localizableTextProvider(withStringsFileFormatKey:, textProviders:)


Are there any official examples of setting up a complication using localizableTextProvider(withStringsFileFormatKey:, textProviders:)? I can get the text provider to populate when producing a SampleTemplate, but whenever I try to generate a template using getTimelineEntries the text provider generated by localizableTextProvider the result is always blank, no text.

Example (only supporting .utilitarianLarge):

func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {  
    // Call the handler with the current timeline entry  
    let template = CLKComplicationTemplateUtilitarianLargeFlat()  

    template.textProvider = CLKTextProvider.localizableTextProvider(  
        withStringsFileFormatKey: "testComplication",  
        textProviders: [  
            CLKSimpleTextProvider(text: "Hello"),  
            CLKSimpleTextProvider(text: "World")  
        ]  
    )  

    handler(CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template))  

}  

and sampleTemplate as

func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {  
    // This method will be called once per supported complication, and the results will be cached  
    switch complication.family {  
    case .utilitarianLarge:  
        let template = CLKComplicationTemplateUtilitarianLargeFlat()  

        template.textProvider = CLKTextProvider.localizableTextProvider(  
            withStringsFileFormatKey: "testComplication",  
            textProviders: [  
                CLKSimpleTextProvider(text: "Hi"),  
                CLKSimpleTextProvider(text: "World")  
            ]  
        )  

        handler(template)  

    default:  
        handler(nil)  
    }  

}  

with ckcomplication.strings as

"testComplication" = "%@ %@";

The sample template will always display the text "Hi World", whereas the result from getCurrentTimelineEntry will always display an empty complication.

Has anyone had luck composing text providers in this way?


Solution

  • It appears this API is just broken in Swift (as of 4.2). I worked around this with an Objective C category. Blatantly stolen from here

    CLKTextProvider+NNNCompoundTextProviding.h

    @interface CLKTextProvider (NNNCompoundTextProviding)
    
    + (nonnull CLKTextProvider *)nnn_textProviderByJoiningProvider:(nonnull CLKTextProvider *)provider1 andProvider:(nonnull CLKTextProvider *)provider2 withString:(nullable NSString *)joinString;
    
    @end
    

    CLKTextProvider+NNNCompoundTextProviding.m

    @implementation CLKTextProvider (NNNCompoundTextProviding)
    
    + (nonnull CLKTextProvider *)nnn_textProviderByJoiningProvider:(nonnull CLKTextProvider *)provider1 andProvider:(nonnull CLKTextProvider *)provider2 withString:(nullable NSString *)joinString
    {
        NSString *textProviderToken = @"%@";
    
        NSString *formatString;
    
        if (joinString != nil) {
            formatString = [NSString stringWithFormat:@"%@%@%@",
                            textProviderToken,
                            joinString,
                            textProviderToken];
        }
        else {
            formatString = [NSString stringWithFormat:@"%@%@",
                            textProviderToken,
                            textProviderToken];
        }
    
        return [self textProviderWithFormat:formatString, provider1, provider2];
    }
    
    @end