Prima aplicație WatchKit Interacțiunea cu utilizatorul

În tutorialul anterior, am analizat fundamentele dezvoltării WatchKit. Am creat un proiect în Xcode, am adăugat o aplicație WatchKit și am creat o interfață de bază pentru utilizatori.

Interfața cu utilizatorul aplicației noastre WatchKit afișează în prezent date statice. Dacă nu locuiți în deșert, acest lucru nu este foarte util pentru o aplicație meteorologică. În acest tutorial, vom popula interfața cu datele și vom crea câteva acțiuni.

1. Actualizarea interfeței utilizator

Pasul 1: Înlocuirea WKInterfaceDate

Înainte de a popula interfața cu datele, trebuie să facem o mică schimbare. În tutorialul anterior, am adăugat a WKInterfaceDate exemplu în partea de jos pentru a afișa ora și data curentă. Ar fi însă mai util să afișăm ora și data datelor afișate. Motivul pentru această schimbare va deveni clar în câteva momente.

Deschis Interface.storyboard, eliminați WKInterfaceDate exemplu în grupul de jos și înlocuiți-l cu un WKInterfaceLabel instanță. Setați eticheta Lăţime atribuit lui În raport cu containerul și eticheta Aliniere la dreapta aliniate.

Pasul 2: Adăugarea ieșirilor

Pentru a actualiza interfața cu datele dinamice, trebuie să creați câteva puncte de desfacere în InterfaceController clasă. Deschideți tabloul de bord în editorul principal și InterfaceController.swift în Editor asistent pe dreapta. Selectați eticheta de început din primul grup și Control-Drag de la etichetă la InterfaceController pentru a crea o priză. Denumiți priza locationLabel.

Repetați acești pași pentru celelalte etichete, denumiți-le temperatureLabel și DATELABEL respectiv. Aceasta este ceea ce InterfaceController clasa ar trebui să arate ca atunci când ați terminat.

import Importul WatchKit Clasa de fundație InterfaceController: WKInterfaceController @IBOutlet weak var dateLabel: WKInterfaceLabel! @IBOutlet slab var locațieLabel: WKInterfaceLabel! @IBOutlet slab var temperaturaLabel: WKInterfaceLabel! override func awakeWithContext (context: AnyObject?) super.awakeWithContext (context) override func willActivate () // Această metodă se numește atunci când controlerul de vizionare a ceasului este pe cale să fie vizibil pentru utilizator super.willActivate () suprascrie func didDeactivate ) // Această metodă se numește atunci când controlerul vizualizare a ceasului nu mai este vizibil super.didDeactivate ()

Acum poate fi un moment bun pentru a examina mai îndeaproape implementarea InterfaceController clasă. În tutorialul anterior, am menționat acest lucru InterfaceController moștenește de la WKInterfaceController. La prima vedere, poate părea că a WKInterfaceController instanța se comportă ca a UIViewController dar, de asemenea, am învățat în tutorialul anterior că există o serie de diferențe majore.

Pentru a ne ajuta, Xcode a populat InterfaceController clasa cu trei metode suprasolicitate. Este important să înțelegeți când se invocă fiecare metodă și pentru ce poate sau ar trebui să fie folosit.

awakeWithContect (_ :)

În awakeWithContext (_ :) , configurați și inițializați controlerul de interfață. S-ar putea să te întrebi cum diferă de la init metodă. awakeWithContext (_ :) metoda este invocată după inițializarea controlerului de interfață. Metoda acceptă un parametru, un obiect de context care permite controlerelor de interfață să transmită informații unul altuia. Aceasta este abordarea recomandată pentru transmiterea informațiilor între scene, adică controlere de interfață.

willActivate

willActivate metoda este similară cu viewWillAppear (_ :) metodă a UIViewController clasă. willActivate metoda este invocată înainte ca interfața utilizator a controlerului de interfață să fie prezentată utilizatorului. Este ideal pentru a personaliza interfața cu utilizatorul înainte de a fi prezentată utilizatorului.

didDeactivate

didDeactivate metoda este contrapartida willActivate și este invocată atunci când scena controlerului de interfață a fost eliminată. Orice cod de curățare merge în această metodă. Această metodă este similară cu viewDidDisappear (_ :) metode găsite în UIViewController clasă.

Având în vedere cele de mai sus, putem începe încărcarea datelor și actualizarea interfeței utilizator a aplicației WatchKit. Să începem cu încărcarea datelor despre vreme.

2. Încărcarea datelor meteo

Cele mai bune practici

S-ar putea să vă gândiți că următorul pas implică un apel API către un serviciu meteorologic, dar nu este cazul. Dacă construim o aplicație pentru iOS, veți avea dreptate. Cu toate acestea, creăm o aplicație WatchKit.

Nu este recomandat să efectuați apeluri API complexe pentru a prelua date pentru a popula interfața utilizator a unei aplicații WatchKit. Chiar dacă Apple nu menționează în mod explicit acest lucru în documentație, un inginer de la Apple a menționat această bună practică nescrisă în forumurile dezvoltatorilor Apple.

Aplicația WatchKit face parte dintr-o aplicație iOS și este aplicația iOS responsabilă de preluarea datelor de pe un backend de la distanță. Există mai multe abordări pe care le putem lua pentru a face acest lucru, înfrângerea fundalului fiind o alegere bună. În acest tutorial, cu toate acestea, nu ne vom concentra pe acest aspect.

În schimb, vom adăuga date fictive în pachetul extensiei WatchKit și îl vom încărca în awakeWithContext (_ :) metodă discutată mai devreme.

Creați un fișier gol selectând Nou> Fișier ...  de la Fişier meniul. Alege Gol de la iOS> Altele și denumiți fișierul weather.json. Verificați dublu că adăugați fișierul la RainDrop WatchKit Extension. Nu treceți cu vederea acest detaliu mic, dar important. Populați fișierul cu următoarele date.

"locații": "locație": "Cupertino", "temperatură": 24, "timestamp": 1427429751, "location": "London", "temperature": 11; "locație": "Paris", "temperatură": 9, "timestamp": 1427429751, "location": "Brussels", "temperature": 11, "timestamp": 1427429751

Partajarea datelor

Schimbul de date între aplicația iOS și aplicația WatchKit este un subiect important. Cu toate acestea, acest tutorial se concentrează pe punerea în funcțiune a primei aplicații WatchKit. Într-un tutorial viitor, mă voi concentra pe partajarea datelor între o aplicație iOS și o aplicație WatchKit.

Chiar dacă nu vom acoperi datele de partajare în acest tutorial, este important să știți că aplicația iOS și extensia WatchKit nu împărtășesc o cutie de nisip. Ambele obiective au propriul lor sandbox și asta face ca schimbul de date să fie mai puțin banal decât pare.

Pentru a partaja date între aplicația iOS și WatchKit, trebuie să utilizați grupurile de aplicații. Dar acesta este un subiect pentru un tutorial viitor.

Pasul 1: Adăugați SwiftyJSON

Swift este un limbaj minunat, dar unele sarcini sunt mai simple în obiectivul C decât în ​​Swift. Manipularea JSON, de exemplu, este o astfel de sarcină. Pentru a ușura această sarcină, am ales să folosesc biblioteca populară SwiftyJSON.

Descărcați depozitul de la GitHub, dezarhivați arhiva și adăugați SwiftyJSON.swift la RainDrop WatchKit Extension grup. Acest fișier este localizat în Sursă dosarul arhivei. Verificați dublu că SwiftyJSON.swift este adăugat RainDrop WatchKit Extension ţintă.

Pasul 2: Implementarea WeatherData

Pentru a facilita lucrul cu datele meteo stocate în weather.json, vom crea o structură numită WeatherData. Selectați Nou> Fișier ... din  Fişier meniu, alegeți Swift File de la iOS> Sursă și denumiți fișierul WeatherData. Asigurați-vă că fișierul este adăugat la RainDrop WatchKit Extension ţintă.

Punerea în aplicare a directivei WeatherData structura este scurtă și simplă. Structura definește trei proprietăți constante, Data, Locație, și temperatura.

import Structura structurii WeatherData data: NSDate permite locatia: String lasa temperatura: Double

Deoarece valoarea temperaturii weather.json este în Celcius, implementăm de asemenea o proprietate calculată fahrenheit pentru o conversie ușoară între Celcius și Fahrenheit.

var fahrentheit: Dublă temperatură de retur * (9/5) + 32

De asemenea, definim două metode de ajutor toCelciusString și toFahrenheitString pentru a ușura valorile de formatare a temperaturii. Nu-ți place interpolarea șirului lui Swift?

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

Cum am spus, punerea în aplicare a WeatherData structura este scurtă și simplă. Aceasta ar trebui să arate modul de implementare.

import Structură de date WeatherData data: NSDate permite locația: String să lase temperatura: Double var fahrentheit: Dublu retur de temperatură * (9/5) + 32 func toCelciusString  func toFahrenheitString () -> String retur "\ (fahrentheit) ° F"

Pasul 3: Încărcarea datelor

Înainte de a încărca datele de la weather.json, trebuie să declarăm o proprietate pentru stocarea datelor meteorologice. Proprietatea, weatherData, este de tip [WeatherData] și va conține conținutul weather.json ca și cazuri de WeatherData structura.

var vremeData: [WeatherData] = []

Pentru ușurința utilizării, declarăm și o proprietate calculată, vreme, care ne dă acces la primul element din weatherData matrice. Datele acestui lucru WeatherData exemplu pe care o vom afișa în controlerul de interfață. Poți să ghici de ce trebuie să declarăm vreme proprietate ca opțional?

Var vremea: WeatherData? return weatherData.first

Încărcăm datele de la weather.json în awakeWithContext (_ :) metodă. Pentru a menține implementarea curată, invocăm o metodă de ajutor numită loadWeatherData.

override func awakeWithContext (context: AnyObject?) super.awakeWithContext (context) // Încărcare date meteo loadWeatherData ()

Implementarea sistemului loadWeatherData este probabil fragmentul de cod cel mai descurajant pe care îl vom vedea în acest tutorial. Cum am spus, parsarea JSON nu este banală în Swift. Din fericire, SwiftyJSON face cea mai mare parte a ridicării grele pentru noi.

functie loadNameData () let path = NSBundle.mainBundle () pathForResource ("weather" dinType: "json" JSON (date: date) permite locatii = weatherData ["locations"] array daca locatiile = locatii pentru locatia in locatii let timestamp = locatia ["timestamp"]. date date = dateData (dataIntervalSinceReferenceDate: timestamp) permite model = WeatherData (data: data, locatia: locatia ["locatia" 

Obținem calea către weather.json și încărcați conținutul său ca un NSData obiect. Utilizăm SwiftyJSON pentru a analiza JSON, trecând în NSData obiect. Obținem o referință la matricea cheii locații și buclă peste fiecare locație.

Normalizăm datele meteo prin convertirea timbrului la un NSDate instanță și inițializați WeatherData obiect. În cele din urmă, adăugăm WeatherData obiecte față de weatherData mulțime.

Sper că sunteți de acord că implementarea nu este atât de dificilă. Deoarece Swift ne obligă să facem o serie de verificări, implementarea pare mai complexă decât este de fapt.

3. Popularea interfeței utilizator

Cu datele meteo gata de utilizare, este timpul să actualizați interfața cu utilizatorul. Așa cum am explicat mai devreme, actualizarea interfeței cu utilizatorul trebuie să se întâmple în willActivate metodă. Să aruncăm o privire asupra implementării acestei metode.

override func willActivate () // Această metodă se numește atunci când controlerul de vizualizare a ceasului este pe cale să fie vizibil pentru utilizator super.willActivate () if let weather = self.weather locationLabel.setText (weather.location) .updateTemperatureLabel () // Actualizare etichetă de dată self.updateDateLabel ()

După invocarea willActivate metoda superclasei, despachetăm valoarea stocată în vreme proprietate. Pentru a actualiza eticheta locației, vom invoca setText, trecerea în valoarea stocată în Locație proprietate a vreme obiect. Pentru a actualiza etichetele de temperatură și date, invocăm două metode de ajutor. Prefer să păstrez willActivate metoda scurtă și concisă și, mai important, nu-mi place să mă repet.

Înainte de a ne uita la aceste metode de ajutor, trebuie să știm dacă temperatura trebuie să fie afișată în Celcius sau Fahrenheit. Pentru a rezolva această problemă, declarați o proprietate, Benzoat, de tip bool și setați valoarea sa inițială la Adevărat.

var celcius: Bool = adevărat

Implementarea sistemului updateTemperatureLabel este ușor de înțeles. Am despachetat în siguranță valoarea stocată în vreme și actualizați eticheta de temperatură pe baza valorii Benzoat. După cum puteți vedea, cele două metode de asistență ale WeatherData structura pe care am creat-o mai devreme este la îndemână.

func updateTemperatureLabel () if let weather = self.weather if self.celcius temperatureLabel.setText (weather.toCelciusString () altceva temperatureLabel.setText (weather.toFahrenheitString ()

Implementarea sistemului updateDateLabel nu este nici dificil. Inițializăm un NSDateFormatter exemplu, setați-o formatul datei de proprietate, și de a converti data vreme obiect prin apel stringFromDate (_ :) pe dateFormatter obiect. Această valoare este utilizată pentru actualizarea etichetei de dată.

func updateDateLabel () var data: NSDate = NSDate () // Initializeaza data Formatter let dateFormattter = NSDateFormatter () // Configureaza formatatorul de date dateFormattter.dateFormat = "d / MM HH: mm" if let weather = self.weather = weather.date // Actualizați data Label dateLabel.setText (dateFormatt.stringFromDate (date))

Construiți și rulați aplicația pentru a vedea rezultatul. Interfața de utilizator ar trebui să fie acum populate cu datele de la weather.json.

4. Trecerea la Fahrenheit

Asta arată bine. Dar nu ar fi minunat să adăugăm sprijin atât pentru Celcius cât și pentru Fahrenheit? Acest lucru este ușor de făcut, deoarece deja am pus cea mai mare parte a bazelor.

Dacă forța utilizatorului atinge interfața de utilizator a unui controler de interfață cu utilizatorul, este afișat un meniu. Desigur, aceasta funcționează numai dacă este disponibil un meniu. Să vedem cum funcționează acest lucru.

Deschis Interface.storyboard și adăugați un meniu la Controller de interfață în Schița documentelor pe stanga. În mod prestabilit, un meniu are un element de meniu. Avem nevoie de două elemente de meniu, astfel încât să adăugăm un alt element de meniu în meniu.

Rețineți că meniul și elementele de meniu nu sunt vizibile în interfața cu utilizatorul. Aceasta nu este o problemă deoarece nu putem configura configurația meniului. Ce putem schimba sunt textul unui element de meniu și imaginea acestuia. Veți înțelege mai bine ce înseamnă asta atunci când prezentăm meniul.

Selectați elementul de meniu de sus, deschideți Atribuții Inspector, a stabilit Titlu la Benzoat, și Imagine la Accept. Selectați elementul din partea de jos și setați Titlu la Fahrenheit și Imagine la Accept.

În continuare, deschideți-vă InterfaceController.swift în Editor asistent pe dreapta. Control-Drag de la elementul de meniu de sus la InterfaceController.swift și să creeze o acțiune numită toCelcius. Repetați acest pas pentru elementul din partea de jos, creând o acțiune numită toFahrenheit.

Punerea în aplicare a acestor acțiuni este scurtă. În toCelcius, verificăm dacă Benzoat proprietatea este setată la fals, și, dacă este, am setat proprietatea la Adevărat. În toFahrenheit, verificăm dacă Benzoat proprietatea este setată la Adevărat, și, dacă este, am setat proprietatea la fals.

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

Dacă valoarea lui Benzoat modificări, trebuie să actualizăm interfața cu utilizatorul. Ce modalitate mai bună de a realiza acest lucru prin punerea în aplicare a unui observator de proprietate pe Benzoat proprietate. Trebuie doar să implementăm a didSet observator de proprietate.

var celcius: Bool = adevărat didSet if celcius! = oldValue updateTemperatureLabel ()

Singurul detaliu care merită menționat este că interfața cu utilizatorul este actualizată numai dacă valoarea lui Benzoat sa schimbat. Actualizarea interfeței cu utilizatorul este la fel de simplă ca și apelarea updateTemperatureLabel. Construiți și executați aplicația WatchKit în Simulatorul iOS pentru a testa meniul.

Merită menționat faptul că simulatorul iOS imită reacția unui dispozitiv fizic. Ce inseamna asta? Amintiți-vă că extensia WatchKit rulează pe un iPhone, în timp ce aplicația WatchKit rulează pe un dispozitiv Apple Watch. Când utilizatorul fixează un element de meniu, evenimentul tactil este trimis printr-o conexiune Bluetooth către iPhone. Extensia WatchKit procesează evenimentul și trimite orice actualizări înapoi la Apple Watch. Această comunicare este destul de rapidă, dar nu este la fel de rapidă ca și când atât extensia, cât și aplicația urmau să ruleze pe același dispozitiv. Această întârziere scurtă este imită de simulatorul iOS pentru a ajuta dezvoltatorii să obțină o idee despre performanță.

Concluzie

Odată ce ați înfășurat capul în jurul arhitecturii unei aplicații WatchKit, devine mult mai ușor să înțelegeți posibilitățile și limitele primei generații de aplicații WatchKit. În acest tutorial, am abordat doar principalele aspecte ale dezvoltării WatchKit. Mai sunt multe de descoperit și de explorat. Rămâneți aproape.

Cod