Ihre erste WatchKit-Anwendung Benutzerinteraktion

Im vorherigen Tutorial haben wir die Grundlagen der Entwicklung von WatchKit untersucht. Wir haben ein Projekt in Xcode erstellt, eine WatchKit-Anwendung hinzugefügt und eine grundlegende Benutzeroberfläche erstellt.

Die Benutzeroberfläche unserer WatchKit-Anwendung zeigt derzeit statische Daten an. Wenn Sie nicht in der Wüste leben, ist dies für eine Wetteranwendung nicht sehr nützlich. In diesem Lernprogramm füllen wir die Benutzeroberfläche mit Daten auf und erstellen einige Aktionen.

1. Aktualisieren der Benutzeroberfläche

Schritt 1: Ersetzen WKInterfaceDate

Bevor wir die Benutzeroberfläche mit Daten füllen, müssen wir eine kleine Änderung vornehmen. Im vorherigen Tutorial haben wir a hinzugefügt WKInterfaceDate Instanz in die unterste Gruppe, um die aktuelle Uhrzeit und das aktuelle Datum anzuzeigen. Es wäre jedoch sinnvoller, Uhrzeit und Datum der angezeigten Daten anzuzeigen. Der Grund für diese Änderung wird in wenigen Augenblicken klar.

Öffnen Interface.storyboard, entferne das WKInterfaceDate Instanz in der unteren Gruppe und ersetzen Sie es mit einem WKInterfaceLabel Beispiel. Legen Sie die Beschriftung fest Breite zuschreiben Relativ zu Container und das Label Ausrichtung nach rechts ausgerichtet.

Schritt 2: Outlets hinzufügen

Um die Benutzeroberfläche mit dynamischen Daten zu aktualisieren, müssen Sie einige Outlets im erstellen InterfaceController Klasse. Öffnen Sie das Storyboard im Haupteditor und InterfaceController.swift in dem Schnittassistenz zur Rechten. Wählen Sie das oberste Etikett in der ersten Gruppe und Control-Drag vom Etikett bis zum InterfaceController Klasse, um eine Steckdose zu schaffen. Benennen Sie die Steckdose locationLabel.

Wiederholen Sie diese Schritte für die anderen Beschriftungen und benennen Sie sie TemperatureLabel und dateLabel beziehungsweise. Das ist was der InterfaceController Die Klasse sollte aussehen, wenn Sie fertig sind.

importieren WatchKit importieren Foundation-Klasse InterfaceController: WKInterfaceController @IBOutlet schwach var dateLabel: WKInterfaceLabel! @IBOutlet schwache var locationLabel: WKInterfaceLabel! @IBOutlet schwache Var TemperatureLabel: WKInterfaceLabel! func awakeWithContext (context: AnyObject?) überschreiben super.awakeWithContext (context) func willActivate () außer Kraft setzen // // Diese Methode wird aufgerufen, wenn der Watch-View-Controller für den Benutzer sichtbar ist. super.willActivate () func didDeactivate () ) // Diese Methode wird aufgerufen, wenn der Watch-View-Controller nicht mehr sichtbar ist. Super.didDeactivate ()

Jetzt ist es an der Zeit, die Implementierung des Systems näher zu betrachten InterfaceController Klasse. Im vorherigen Tutorial habe ich das erwähnt InterfaceController erbt von WKInterfaceController. Auf den ersten Blick kann es so aussehen, als ob a WKInterfaceController Instanz verhält sich wie eine UIViewController Beispiel, aber wir haben auch im vorigen Tutorial gelernt, dass es einige wichtige Unterschiede gibt.

Um uns zu helfen, hat Xcode die InterfaceController Klasse mit drei überschriebenen Methoden. Es ist wichtig zu verstehen, wann jede Methode aufgerufen wird und wofür sie verwendet werden kann oder soll.

awakeWithContect (_ :)

In dem awakeWithContext (_ :) Methode einrichten und initialisieren Sie den Schnittstellencontroller. Sie fragen sich vielleicht, wie es sich von der unterscheidet drin Methode. Das awakeWithContext (_ :) Die Methode wird aufgerufen, nachdem der Schnittstellencontroller initialisiert wurde. Die Methode akzeptiert einen Parameter, ein Kontextobjekt, mit dem Schnittstellencontroller Informationen aneinander übergeben können. Dies ist der empfohlene Ansatz für die Weitergabe von Informationen zwischen Szenen, dh Schnittstellensteuerungen.

willActivate

Das willActivate Methode ist ähnlich der viewWillAppear (_ :) Methode der UIViewController Klasse. Das willActivate Die Methode wird aufgerufen, bevor dem Benutzer die Benutzeroberfläche des Schnittstellencontrollers angezeigt wird. Es ist ideal, um die Benutzeroberfläche zu optimieren, bevor sie dem Benutzer präsentiert wird.

didDeactivate

Das didDeactivate Methode ist das Gegenstück zum willActivate Methode und wird aufgerufen, wenn die Szene des Schnittstellencontrollers entfernt wurde. Jeglicher Bereinigungscode wird in diese Methode übernommen. Diese Methode ähnelt der viewDidDisappear (_ :) Methode gefunden in der UIViewController Klasse.

Aus diesem Grund können wir mit dem Laden von Daten beginnen und die Benutzeroberfläche unserer WatchKit-Anwendung aktualisieren. Beginnen wir mit dem Laden der Wetterdaten.

2. Wetterdaten laden

Best Practices

Sie denken vielleicht, dass der nächste Schritt einen API-Aufruf an einen Wetterdienst beinhaltet, aber das ist nicht der Fall. Wenn wir eine iOS-Anwendung erstellen, haben Sie recht. Wir erstellen jedoch eine WatchKit-Anwendung.

Es wird nicht empfohlen, komplexe API-Aufrufe auszuführen, um Daten abzurufen, um die Benutzeroberfläche einer WatchKit-Anwendung aufzufüllen. Obwohl Apple dies nicht ausdrücklich in der Dokumentation erwähnt, hat ein Apple-Ingenieur diese ungeschriebene Best Practice in den Entwicklerforen von Apple erwähnt.

Die WatchKit-Anwendung ist Teil einer iOS-Anwendung, und die iOS-Anwendung ist für das Abrufen von Daten von einem Remote-Backend verantwortlich. Es gibt verschiedene Ansätze, um dies zu tun, wobei das Abrufen im Hintergrund eine gute Wahl ist. In diesem Tutorial werden wir uns jedoch nicht auf diesen Aspekt konzentrieren.

Stattdessen fügen wir dem Bundle der WatchKit-Erweiterung Dummy-Daten hinzu und laden sie in die awakeWithContext (_ :) Methode, die wir zuvor besprochen haben.

Erstellen Sie eine leere Datei, indem Sie auswählen Neu> Datei…  von dem Datei Speisekarte. Wählen Leeren von dem iOS> Andere Abschnitt und benennen Sie die Datei weather.json. Vergewissern Sie sich noch einmal, dass Sie die Datei in das Verzeichnis aufgenommen haben RainDrop WatchKit-Erweiterung. Übersehen Sie dieses kleine, aber wichtige Detail nicht. Füllen Sie die Datei mit den folgenden Daten.

"standorte": ["standort": "cupertino", "temperatur": 24, "zeitstempel": 1427429751, "standort": "london", "temperatur": 11, "zeitstempel": 1427429751, "location": "Paris", "Temperatur": 9, "Zeitstempel": 1427429751, "location": "Brüssel", "Temperatur": 11, "Zeitstempel": 1427429751]

Daten teilen

Die gemeinsame Nutzung von Daten zwischen der iOS-Anwendung und der WatchKit-Anwendung ist ein wichtiges Thema. Dieses Tutorial konzentriert sich jedoch darauf, Ihre erste WatchKit-Anwendung zum Laufen zu bringen. In einem zukünftigen Lernprogramm werde ich mich darauf konzentrieren, Daten zwischen einer iOS- und einer WatchKit-Anwendung auszutauschen.

Obwohl wir in diesem Lernprogramm nicht auf die gemeinsame Nutzung von Daten eingehen, ist es wichtig zu wissen, dass die iOS-Anwendung und die WatchKit-Erweiterung keine Sandbox gemeinsam nutzen. Beide Ziele verfügen über eine eigene Sandbox. Daher ist das Teilen von Daten weniger trivial als es scheint.

Um Daten für iOS und die WatchKit-Anwendung gemeinsam zu nutzen, müssen Sie App-Gruppen nutzen. Aber das ist ein Thema für ein zukünftiges Tutorial.

Schritt 1: Hinzufügen von SwiftyJSON

Swift ist eine großartige Sprache, aber einige Aufgaben sind in Objective-C einfacher als in Swift. Der Umgang mit JSON ist beispielsweise eine solche Aufgabe. Um diese Aufgabe zu vereinfachen, habe ich mich für die beliebte SwiftyJSON-Bibliothek entschieden.

Laden Sie das Repository von GitHub herunter, entpacken Sie das Archiv und fügen Sie es hinzu SwiftyJSON.swift zum RainDrop WatchKit-Erweiterung Gruppe. Diese Datei befindet sich im Quelle Ordner des Archivs. Überprüfen Sie das noch einmal SwiftyJSON.swift wird das hinzugefügt RainDrop WatchKit-Erweiterung Ziel.

Schritt 2: Implementieren Wetterdaten

Um die Arbeit mit den in gespeicherten Wetterdaten zu erleichtern weather.json, Wir werden eine Struktur mit dem Namen erstellen Wetterdaten. Wählen Neu> Datei… von das Datei Menü wählen Swift File von dem iOS> Quelle Abschnitt und benennen Sie die Datei Wetterdaten. Vergewissern Sie sich, dass die Datei dem hinzugefügt wurde RainDrop WatchKit-Erweiterung Ziel.

Die Umsetzung der Wetterdaten Struktur ist kurz und einfach. Die Struktur definiert drei konstante Eigenschaften, Datum, Standort, und Temperatur.

Foundation-Struktur importieren WeatherData let date: NSDate let location: Zeichenfolge let temperature: Double

Weil der Temperaturwert von weather.json In Celcius implementieren wir auch eine berechnete Eigenschaft Fahrenheit für eine einfache Umrechnung zwischen Celcius und Fahrenheit.

var fahrentheit: Double Rücklauftemperatur * (9/5) + 32

Wir definieren auch zwei Hilfsmethoden toCelciusString und toFahrenheitString um die Formatierung der Temperaturwerte zu erleichtern. Lieben Sie nicht Swifts String-Interpolation?

func toCelciusString () -> String return "\ (Temperatur) ° C" func toFahrenheitString () -> String return "\ (fahrentheit) ° F"

Wie gesagt, die Umsetzung der Wetterdaten Struktur ist kurz und einfach. So sollte die Implementierung aussehen.

Foundation-Struktur importieren WeatherData let date: NSDate let Speicherort: String let Temperatur: Double var fahrentheit: Double Rücklauftemperatur * (9/5) + 32 func toCelciusString () -> String return "\ (Temperatur) ° C"  func toFahrenheitString () -> String return "\ (fahrentheit) ° F"

Schritt 3: Daten laden

Bevor wir die Daten von laden weather.json, Wir müssen eine Eigenschaft zum Speichern der Wetterdaten angeben. Die Eigenschaft, weatherData, ist vom Typ [Wetterdaten] und enthält den Inhalt von weather.json als Instanzen des Wetterdaten Struktur.

var weatherData: [WeatherData] = []

Zur Vereinfachung der Verwendung deklarieren wir auch eine berechnete Eigenschaft, Wetter, das gibt uns Zugang zum ersten Punkt der weatherData Array. Es sind die Daten davon Wetterdaten Instanz, die wir in der Schnittstellensteuerung anzeigen. Können Sie sich vorstellen, warum wir das erklären müssen? Wetter Eigenschaft als optional?

var Wetter: Wetterdaten? return weatherData.first

Wir laden die Daten von weather.json in dem awakeWithContext (_ :) Methode. Um die Implementierung sauber zu halten, rufen wir eine Hilfsmethode namens auf loadWeatherData.

func awakeWithContext überschreiben (Kontext: AnyObject?) super.awakeWithContext (Kontext) // Wetterdaten laden loadWeatherData ()

Die Implementierung von loadWeatherData ist wahrscheinlich das entmutigendste Code-Snippet, das wir in diesem Tutorial sehen werden. Wie gesagt, das Parsen von JSON ist in Swift nicht trivial. Glücklicherweise erledigt SwiftyJSON den größten Teil des Schwerhebens für uns.

func loadWeatherData () let path = NSBundle.mainBundle (). pathForResource ("weather", ofType: "json") wenn let Pfad = Pfad let data = NSData (contentsOfFile: path) ist, wenn data = data let weatherData = JSON (data: data) let Standort = Wetterdaten ["Locations"]. Array, wenn Locations = Standorte für Standort in Locations let timestamp = Standort ["timestamp"]. Double! let date = NSDate (timeIntervalSinceReferenceDate: timestamp) let model = WeatherData (Datum: Datum, Ort: location ["location"]. string !, Temperatur: location ["temperature"]. double!) self.weatherData.append (model) 

Wir erhalten den Weg zu weather.json und laden Sie den Inhalt als NSData Objekt. Wir verwenden SwiftyJSON, um die JSON zu analysieren, und übergeben die NSData Objekt. Wir erhalten einen Verweis auf das Array für den Schlüssel Standorte und Schleife über jeden Ort.

Wir normalisieren die Wetterdaten, indem wir den Zeitstempel in ein konvertieren NSDate Instanz und initialisieren a Wetterdaten Objekt. Zum Schluss fügen wir die Wetterdaten Einwände gegen die weatherData Array.

Ich hoffe, Sie stimmen zu, dass die Implementierung nicht so schwierig ist. Da Swift uns zu einer Reihe von Prüfungen zwingt, wirkt die Implementierung komplexer als sie tatsächlich ist.

3. Auffüllen der Benutzeroberfläche

Wenn die Wetterdaten einsatzbereit sind, ist es Zeit, die Benutzeroberfläche zu aktualisieren. Wie ich bereits erklärt habe, muss die Aktualisierung der Benutzeroberfläche in der vorgenommen werden willActivate Methode. Lassen Sie uns einen Blick auf die Implementierung dieser Methode werfen.

override func willActivate () // Diese Methode wird aufgerufen, wenn der Watch-View-Controller für den Benutzer super.willActivate () sichtbar ist, wenn weather = self.weather locationLabel.setText (weather.location) // Update Temperature Label self .updateTemperatureLabel () // Update Datumsbezeichnung self.updateDateLabel ()

Nach dem Aufruf der willActivate Methode der Superklasse, wir wickeln den in der gespeicherten Wert aus Wetter Eigentum. Um die Standortbezeichnung zu aktualisieren, rufen wir auf Text setzen, Übergabe des Wertes, der im gespeichert ist Standort Eigentum der Wetter Objekt. Um die Temperatur- und Datums-Labels zu aktualisieren, rufen wir zwei Hilfsmethoden auf. Ich ziehe es vor, die willActivate Methode kurz und prägnant, und vor allem möchte ich mich nicht wiederholen.

Bevor wir uns diese Hilfsmethoden anschauen, müssen wir wissen, ob die Temperatur in Celsius oder Fahrenheit angezeigt werden muss. Um dieses Problem zu beheben, deklarieren Sie eine Eigenschaft, Celcius, vom Typ Bool und setzen Sie ihren Anfangswert auf wahr.

var celcius: Bool = wahr

Die Implementierung von updateTemperatureLabel ist leicht zu verstehen. Wir packen den Wert sicher aus Wetter und aktualisieren Sie das Temperaturetikett basierend auf dem Wert von Celcius. Wie Sie sehen können, sind die beiden Hilfsmethoden des Wetterdaten Struktur, die wir zuvor erstellt haben, ist praktisch.

func updateTemperatureLabel () wenn Wetter = self.weather wenn self.celcius temperatureLabel.setText (weather.toCelciusString ()) else temperatureLabel.setText (weather.toFahrenheitString ())

Die Implementierung von updateDateLabel ist auch nicht schwierig. Wir initialisieren ein NSDateFormatter Beispiel, setzen Sie seine Datumsformat Eigenschaft, und konvertieren Sie das Datum der Wetter Objekt durch Aufruf stringFromDate (_ :) auf der dateFormatter Objekt. Dieser Wert wird zum Aktualisieren der Datumsbezeichnung verwendet.

func updateDateLabel () var date: NSDate = NSDate () // Datumsformatierer initialisieren let dateFormattter = NSDateFormatter () // Datumsformatierer konfigurieren dateFormattter.dateFormat = "d / MM HH: mm", wenn Wetter = Selbstwetter Datum ist = weather.date // Update Datumsbezeichnung dateLabel.setText (dateFormattter.stringFromDate (date))

Erstellen Sie die Anwendung, und führen Sie sie aus, um das Ergebnis anzuzeigen. Die Benutzeroberfläche sollte jetzt mit den Daten von gefüllt werden weather.json.

4. Umschalten auf Fahrenheit

Das sieht gut aus. Aber wäre es nicht großartig, wenn wir Celcius und Fahrenheit zusätzlich unterstützen würden? Dies ist einfach zu bewerkstelligen, da wir bereits die meisten Vorarbeiten geleistet haben.

Wenn der Benutzer die Benutzeroberfläche einer Benutzeroberflächensteuerung berührt, wird ein Menü angezeigt. Das funktioniert natürlich nur, wenn ein Menü verfügbar ist. Mal sehen, wie das funktioniert.

Öffnen Interface.storyboard und fügen Sie ein Menü hinzu Schnittstellen-Controller in dem Dokument Gliederung auf der Linken. Standardmäßig hat ein Menü einen Menüpunkt. Wir benötigen zwei Menüpunkte, also fügen Sie dem Menü einen weiteren Menüpunkt hinzu.

Beachten Sie, dass das Menü und seine Menüelemente in der Benutzeroberfläche nicht sichtbar sind. Dies ist kein Problem, da wir das Layout des Menüs nicht konfigurieren können. Was wir ändern können, ist der Text eines Menüelements und sein Bild. Sie verstehen besser, was das bedeutet, wenn wir das Menü präsentieren.

Wählen Sie den obersten Menüpunkt aus, öffnen Sie die Attribute-Inspektor, einstellen Titel zu Celcius, und Bild zu Akzeptieren. Wählen Sie den unteren Menüpunkt und legen Sie fest Titel zu Fahrenheit und Bild zu Akzeptieren.

Als nächstes öffnen InterfaceController.swift in dem Schnittassistenz zur Rechten. Control-Drag vom obersten Menüpunkt bis InterfaceController.swift und erstellen Sie eine Aktion mit dem Namen toCelcius. Wiederholen Sie diesen Schritt für den unteren Menüpunkt und erstellen Sie eine Aktion mit dem Namen toFahrenheit.

Die Umsetzung dieser Maßnahmen ist kurz. Im toCelcius, Wir prüfen, ob die Celcius Eigenschaft ist auf gesetzt falsch, und wenn ja, setzen wir die Eigenschaft auf wahr. Im toFahrenheit, Wir prüfen, ob die Celcius Eigenschaft ist auf gesetzt wahr, und wenn ja, setzen wir die Eigenschaft auf falsch.

@IBAction func toCelcius () if! Self.celcius self.celcius = true @IBAction func toFahrenheit () wenn self.celcius self.celcius = false

Wenn der Wert von Celcius Änderungen müssen wir die Benutzeroberfläche aktualisieren. Welchen besseren Weg kann dies durch die Implementierung eines Immobilienbeobachters auf der Celcius Eigentum. Wir müssen nur ein implementieren didSet Immobilienbeobachter.

var celcius: Bool = true didSet if celcius! = oldValue updateTemperatureLabel ()

Das einzige erwähnenswerte Detail ist, dass die Benutzeroberfläche nur dann aktualisiert wird, wenn der Wert von Celcius hat sich geändert Das Aktualisieren der Benutzeroberfläche ist so einfach wie das Aufrufen updateTemperatureLabel. Erstellen und starten Sie die WatchKit-Anwendung im iOS-Simulator, um das Menü zu testen.

Es ist erwähnenswert, dass der iOS-Simulator die Reaktionsfähigkeit eines physischen Geräts nachahmt. Was bedeutet das? Denken Sie daran, dass die WatchKit-Erweiterung auf einem iPhone ausgeführt wird, während die WatchKit-Anwendung auf einer Apple Watch läuft. Wenn der Benutzer auf ein Menüelement tippt, wird das Berührungsereignis über eine Bluetooth-Verbindung an das iPhone gesendet. Die WatchKit-Erweiterung verarbeitet das Ereignis und sendet alle Aktualisierungen an die Apple Watch zurück. Diese Kommunikation ist ziemlich schnell, aber sie ist nicht so schnell, als würden sowohl die Erweiterung als auch die Anwendung auf demselben Gerät laufen. Diese kurze Verzögerung wird vom iOS-Simulator nachgeahmt, damit Entwickler eine Vorstellung von der Leistung bekommen.

Fazit

Wenn Sie sich erst einmal mit der Architektur einer WatchKit-Anwendung beschäftigt haben, werden Sie die Möglichkeiten und Einschränkungen der ersten Generation von WatchKit-Anwendungen viel leichter verstehen. In diesem Lernprogramm haben wir nur die Grundlagen der WatchKit-Entwicklung behandelt. Es gibt noch viel mehr zu entdecken und zu erkunden. Bleib dran.