watchOS 3 Tutorial: Complications

Mit einer Complication kann die Uhr der Apple Watch um zusätzliche Informationselemente erweitert werden. Das folgende Tutorial richtet sich an iOS-Entwickler und zeigt die Implementierung einer Complication, die anzeigt, wieviel vom aktuellen Tag noch verbleibt:

Complication Clock Face

Verwenden Sie für dieses Tutorial die aktuelle Version von Xcode 8 (dieses Tutorial wurde zuletzt getestet am 15.2.2017 mit Xcode 8.2).

  1. Erstellen Sie mit File > New > Project > watchOS > Application > iOS App with WatchKit App ein neues iOS-App-Projekt mit WatchKit App:

    Create new iOS App with WatchKit App:

  2. Geben Sie als Projektname DayProgress an. Achten Sie darauf, dass als Programmiersprache Swift ausgewählt ist und wählen Sie alle Optionen bis auf „Include Complication“ ab:

    Project Settings
  3. Öffnen Sie die Konfiguration des DayProgress WatchKit Extension-Targets und wählen Sie hier die Complications Modular Small und Utilitarian Small:

    Complication: Supported Families

    Eine Übersicht der Complication-Arten finden Sie im App Programming Guide for watchOS: Complication Families.

Templates konfigurieren

Während der Auswahl der Complication durch den Anwender wird ein statisches Template angezeigt:

Complication Template: Modular Small

Diese Vorlage kann über eine Asset-Grafik oder über den ComplicationController konfiguriert werden. Im Folgenden kommen beide Varianten zum Einsatz:

  1. Konfigurieren Sie für die Modular-Complication über die Assets.xcassets in der Extension Grafiken (52x52px und 58x58px - Beispielgrafiken):

    Complication Assets
  2. Konfigurieren Sie im ComplicationController zusätzlich ein Template für Utilitarian Small und erzeugen Sie ein CLKComplicationTemplateUtilitarianSmallRingText und befüllen es so, dass angezeigt wird, wieviel vom aktuellen Tag bereits vergangen ist. Mit folgendem Code können Sie die entsprechenden Datumsberechnungen vornehmen:

    import ClockKit
    
    class ComplicationController: NSObject, CLKComplicationDataSource {
        
        // ...
        
        // MARK: - Placeholder Templates
        
        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
    
            if complication.family == .utilitarianSmall {
        let template = CLKComplicationTemplateUtilitarianSmallRingText()
        template.textProvider = CLKSimpleTextProvider(text: "")
        template.fillFraction = self.dayFraction
        handler(template)
    } else {
        handler(nil)
    }
        }
    
        var dayFraction : Float {
        let now = Date()
        let calendar = Calendar.current
        let componentFlags = Set<Calendar.Component>([.year, .month, .day, .weekOfYear,     .hour, .minute, .second, .weekday, .weekdayOrdinal])
        var components = calendar.dateComponents(componentFlags, from: now)
        components.hour = 0
        components.minute = 0
        components.second = 0
        let startOfDay = calendar.date(from: components)!
        return Float(now.timeIntervalSince(startOfDay)) / Float(24*60*60)
    }
        
    }
  3. Starten Sie die Complication mit dem Schema für die Complication:

    Complication Scheme

    Hinweis: Dieses Schema ist so konfiguriert, dass nicht die Watch-App angezeigt wird, sondern die Clock Face der Uhr:

    Schema: Watch Interface
  4. Drücken Sie im Watch-Simulator per Trackpad fest, um einen Deep Press auszulösen (siehe im Simulator-Menü: Hardware > Touch Pressure) und die Clock Face anzupassen. Wählen Sie für die Modular oder Utility-Clock Face die erstellte Complication aus und prüfen Sie, dass die konfigurierten Templates entsprechend angezeigt werden:

    Complication Template: Modular Small Complication Template: Utilitarian Small

Aktuellen Eintrag aktualisieren

  1. Deaktivieren Sie im ComplicationController Time Travel (dies wird in diesem Tutorial nicht behandelt):

    // MARK: - Timeline Configuration
    
    func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
        handler([])
    }
  2. Implementieren Sie getCurrentTimelineEntryForComplication so, dass die entsprechenden Templates erzeugt und befüllt werden:

    // MARK: - Timeline Population
    
    func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
        
        switch complication.family {
    
        case .modularSmall:
            let template = CLKComplicationTemplateModularSmallRingText()
            template.textProvider = CLKSimpleTextProvider(text: "")
            template.fillFraction = self.dayFraction
            handler(CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template))
    
        case .utilitarianSmall:
            let template = CLKComplicationTemplateUtilitarianSmallRingText()
            template.textProvider = CLKSimpleTextProvider(text: "")
            template.fillFraction = self.dayFraction
            handler(CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template))
    
        default:
            NSLog("%@", "Unknown complication type: \(complication.family)")
            handler(nil)
        }
    
        
    }
  3. Implementieren Sie die getNextRequestedUpdateDateWithHandler-Methode und lösen Sie hier eine Aktualisierung in 10 Minuten aus:

    // MARK: - Update Scheduling
    
    func getNextRequestedUpdateDate(handler: @escaping (Date?) -> Void) {
        handler(Date(timeIntervalSinceNow: TimeInterval(10*60)))
    }
  4. Entfernen Sie alle verbleibenden Methoden in der ComplicationController-Klasse: Diese sind optional und werden lediglich für Time Travel benötigt bzw. können verwendet werden, die Implementierung zu optimieren, indem statt einem einzelnen Timeline-Eintrag für die aktuelle Zeit eine Timeline mit folgenden Ereignissen erzeugt wird.

  5. Starten Sie die Complication und prüfen Sie, dass die Anzeige korrekt erfolgt:

    Complication Clock Face

Beispielprojekt

Weitere Informationen

Ralf Ebert Ralf Ebert ist langjähriger Entwickler für iOS und OS X und vermittelt in seinem Xcode-Buch seine Kenntnisse und Erfahrungswerte aus 5 Jahren Tätigkeit als Entwickler für OS X und iOS. Er hat mehrere Apps für Mac, iPhone und iPad konzipiert und entwickelt und vertreibt seine Apps erfolgreich über den App Store. Seit 2009 gibt er sein Know-How in iOS-Kursen für Softwareentwickler weiter, die von den Teilnehmern stets ausgezeichnet bewertet werden.