Ditt første WatchKit-program Brukerinteraksjon

I den tidligere opplæringen, undersøkte vi grunnleggende for WatchKit-utviklingen. Vi opprettet et prosjekt i Xcode, lagt til et WatchKit-program, og opprettet et grunnleggende brukergrensesnitt.

Brukergrensesnittet i WatchKit-applikasjonen viser nå statiske data. Med mindre du bor i ørkenen, er det ikke veldig nyttig for et værprogram. I denne opplæringen skal vi fylle ut brukergrensesnittet med data og opprette et par handlinger.

1. Oppdaterer brukergrensesnittet

Trinn 1: Bytte ut WKInterfaceDate

Før vi fyller brukergrensesnittet med data, må vi gjøre en liten endring. I den forrige veiledningen la vi til en WKInterfaceDate forekomme til den nederste gruppen for å vise gjeldende tid og dato. Det ville imidlertid være mer nyttig å vise tid og dato for dataene vi viser. Årsaken til denne endringen vil bli klart om noen få øyeblikk.

Åpen Interface.storyboard, fjern WKInterfaceDate forekommer i bunnen gruppen og erstatter den med a WKInterfaceLabel forekomst. Sett etiketten Bredde tilskrive I forhold til container og etiketten er Justering til høyre justert.

Trinn 2: Legge til utsalgssteder

For å oppdatere brukergrensesnittet med dynamiske data, må vi opprette et par utsalgssteder i InterfaceController klasse. Åpne storyboardet i hovedredigeren og InterfaceController.swift i Assistent Editor til høyre. Velg toppetiketten i den første gruppen og Kontroll-Drag fra etiketten til InterfaceController klasse for å skape et uttak. Navn på uttaket locationLabel.

Gjenta disse trinnene for de andre etikettene, og navngi dem temperatureLabel og DATELABEL henholdsvis. Dette er hva InterfaceController Klassen skal se ut når du er ferdig.

importere WatchKit import Foundation class InterfaceController: WKInterfaceController @IBOutlet svak var dateLabel: WKInterfaceLabel! @IBOutlet svak var locationLabel: WKInterfaceLabel! @IBOutlet svak var temperatureLabel: WKInterfaceLabel! overstyre func awakeWithContext (kontekst: AnyObject?) super.awakeWithContext (kontekst) overstyr func willActivate () // Denne metoden kalles når overvåkings kontrolleren er i ferd med å være synlig for brukeren super.willActivate () overstyr func didDeactivate ( ) // Denne metoden kalles når overvåkningskontrollen ikke lenger er synlig super.didDeactivate ()

Nå kan det være en god tid å ta en nærmere titt på implementeringen av InterfaceController klasse. I den forrige veiledningen nevnte jeg det InterfaceController arver fra WKInterfaceController. Ved første øyekast kan det virke som om en WKInterfaceController forekomst oppfører seg som a UIViewController eksempel, men vi har også lært i den forrige opplæringen at det er en rekke sentrale forskjeller.

For å hjelpe oss har Xcode befolket InterfaceController klasse med tre overridden metoder. Det er viktig å forstå når hver metode er påkalt og hva den kan eller skal brukes til.

awakeWithContect (_ :)

I awakeWithContext (_ :) Metode, du setter opp og initialiserer grensesnittkontrolleren. Du lurer kanskje på hvordan det adskiller seg fra i det metode. De awakeWithContext (_ :) Metoden påberopes etter at grensesnittkontrolleren er initialisert. Metoden aksepterer en parameter, en kontekstobjekt som tillater grensesnittkontrollere å sende informasjon til hverandre. Dette er den anbefalte tilnærmingen for å sende informasjon på tvers av scener, det vil si grensesnittkontrollere.

willActivate

De willActivate Metoden ligner på viewWillAppear (_ :) metode av UIViewController klasse. De willActivate Metoden påberopes før brukergrensesnittet til grensesnittkontrolleren presenteres for brukeren. Det er ideelt for å tilpasse brukergrensesnittet før det presenteres for brukeren.

didDeactivate

De didDeactivate Metoden er motstykket til willActivate metode og påberopes når scenen til grensesnittkontrolleren er fjernet. Enhver oppryddingskode går inn i denne metoden. Denne metoden ligner på viewDidDisappear (_ :) metode funnet i UIViewController klasse.

Med det ovenfor nevnte kan vi begynne å laste inn data og oppdatere brukergrensesnittet i WatchKit-programmet. La oss starte med å laste værdata.

2. Laster værdata

Beste praksis

Du kan tenke at det neste trinnet innebærer et API-anrop til en værservice, men det er ikke tilfelle. Hvis vi skulle bygge et iOS-program, ville du ha rett. Vi oppretter imidlertid et WatchKit-program.

Det anbefales ikke å lage komplekse API-anrop for å hente data for å fylle ut brukergrensesnittet til et WatchKit-program. Selv om Apple ikke uttrykkelig nevner dette i dokumentasjonen, nevnte en Apple-ingeniør denne uskrevne beste praksisen i Apples utviklerfora.

WatchKit-programmet er en del av et iOS-program, og det er iOS-programmet som har ansvaret for å hente data fra en ekstern backend. Det er flere tilnærminger vi kan ta for å gjøre dette, og henting av bakgrunnen er et godt valg. I denne opplæringen vil vi imidlertid ikke fokusere på dette aspektet.

I stedet legger vi dummy-data til bunten i WatchKit-utvidelsen og laster den inn i awakeWithContext (_ :) metode vi diskuterte tidligere.

Opprett en tom fil ved å velge Ny> Fil ...  fra Fil Meny. Velge Tømme fra iOS> Annet delen og navngi filen weather.json. Dobbeltklikk at du legger filen til RainDrop WatchKit Extension. Ikke overse denne lille, men viktige detaljen. Befolk filen med følgende data.

"steder": ["sted": "Cupertino", "temperatur": 24, "tidsstempel": 1427429751, "plassering": "London", "temperatur": 11, "tidsstempel": 1427429751 "plassering": "Paris", "temperatur": 9, "tidsstempel": 1427429751, "plassering": "Brussel", "temperatur": 11, "tidsstempel": 1427429751]

Deling av data

Deling av data mellom iOS-programmet og WatchKit-programmet er et viktig tema. Denne veiledningen fokuserer imidlertid på å få ditt første WatchKit-program oppe og i gang. I en fremtidig opplæring vil jeg fokusere på å dele data mellom et iOS og et WatchKit-program.

Selv om vi ikke vil dekke deling av data i denne opplæringen, er det viktig å vite at iOS-programmet og WatchKit-utvidelsen ikke deler en sandkasse. Begge målene har sin egen sandkasse, og det er det som gjør deling av data mindre trivial enn det ser ut til.

For å dele data mellom iOS og WatchKit-programmet, må du utnytte appgrupper. Men det er et emne for en fremtidig opplæring.

Trinn 1: Legge til SwiftyJSON

Swift er et flott språk, men noen oppgaver er enklere i Objective-C enn de er i Swift. Håndtering av JSON er for eksempel en slik oppgave. For å gjøre denne oppgaven enklere, har jeg valgt å utnytte det populære SwiftyJSON-biblioteket.

Last ned depotet fra GitHub, pakke ut arkivet og legg til SwiftyJSON.swift til RainDrop WatchKit Extension gruppe. Denne filen er plassert i Kilde Arkivmappe. Dobbeltklikk det SwiftyJSON.swift er lagt til RainDrop WatchKit Extension mål.

Trinn 2: Implementering værdata

For å gjøre det enklere å arbeide med værdata som er lagret i weather.json, Vi skal lage en struktur som heter værdata. Å velge Ny> Fil ... fra de Fil meny, velg Swift File fra iOS> Kilde seksjonen, og navngi filen værdata. Kontroller at filen er lagt til i RainDrop WatchKit Extension mål.

Gjennomføringen av værdata strukturen er kort og enkel. Strukturen definerer tre konstante egenskaper, Dato, plassering, og temperatur.

importere Foundation struktur WeatherData la date: NSDate la sted: String la temperatur: Dobbel

Fordi temperaturverdien på weather.json er i Celcius, implementerer vi også en beregnet eiendom fahrenheit for enkel omstilling mellom Celcius og Fahrenheit.

var fahrentheit: Dobbel returtemperatur * (9/5) + 32

Vi definerer også to hjelpemetoder toCelciusString og toFahrenheitString for å gjøre formateringstemperaturene enklere. Elsker du ikke Swifts strenginterpolering?

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

Som jeg sa, implementeringen av værdata strukturen er kort og enkel. Dette er hva implementeringen skal se ut.

import Stiftelsesstruktur WeatherData la dato: NSDate la sted: String la temperatur: Dobbel var fahrentheit: Dobbel retur temperatur * (9/5) + 32 func toCelciusString () -> String retur "\ (temperatur) ° C"  func toFahrenheitString () -> String return "\ (fahrentheit) ° F"

Trinn 3: Laster inn data

Før vi laster dataene fra weather.json, Vi må deklarere en eiendom for å lagre værdataene. Eiendommen, værdata, er av typen [Værdata] og vil inneholde innholdet i weather.json som tilfeller av værdata struktur.

var weatherData: [WeatherData] = []

For enkel bruk, erklærer vi også en beregnet eiendom, vær, som gir oss tilgang til det første elementet i værdata array. Det er dataene til dette værdata eksempel som vi vil vise i grensesnittkontrolleren. Kan du gjette hvorfor vi må deklarere vær eiendom som valgfritt?

var Vær: WeatherData? return weatherData.first

Vi laster dataene fra weather.jsonawakeWithContext (_ :) metode. For å holde implementeringen ren, kaller vi en hjelpemetode som heter loadWeatherData.

overstyr func awakeWithContext (kontekst: AnyObject?) super.awakeWithContext (kontekst) // Last vær data loadWeatherData ()

Gjennomføringen av loadWeatherData er trolig den mest skremmende kodestykket vi vil se i denne opplæringen. Som sagt, parsing JSON er ikke trivielt i Swift. Heldigvis gjør SwiftyJSON det meste av det tunge løftet for oss.

funk loadWeatherData () let path = NSBundle.mainBundle (). pathForResource ("weather", ofType: "json") hvis la banen = banen la data = NSData (contentOfFile: bane) hvis la data = data la weatherData = JSON (data: data) la steder = weatherData ["locations"]. Array hvis la steder = steder for plassering på steder let timestamp = location ["timestamp"]. la dato = NSDate (timeIntervalSinceReferenceDate: tidsstempel) la modell = WeatherData (dato: dato, sted: sted ["sted"]. streng !, temperatur: sted ["temperatur"]. dobbelt!) self.weatherData.append (modell) 

Vi får veien til weather.json og last inn innholdet som en NSData gjenstand. Vi bruker SwiftyJSON til å analysere JSON, passerer i NSData gjenstand. Vi får en referanse til matrisen for nøkkelen steder og loop over hvert sted.

Vi normaliserer værdataene ved å konvertere tidsstempel til en NSDate forekomst og initialiser a værdata gjenstand. Til slutt legger vi til værdata protestere mot værdata matrise.

Jeg håper du er enig i at implementeringen ikke er så vanskelig. Fordi Swift tvinger oss til å foreta en rekke kontroller, ser implementeringen seg mer komplisert ut enn den faktisk er.

3. Populere brukergrensesnittet

Med værdataene klare til bruk, er det på tide å oppdatere brukergrensesnittet. Som jeg forklarte tidligere, må oppdatering av brukergrensesnittet skje i willActivate metode. La oss se på implementeringen av denne metoden.

overstyr func willActivate () // Denne metoden kalles når overvåkings kontrolleren er i ferd med å være synlig for brukeren super.willActivate () hvis la været = self.weather locationLabel.setText (weather.location) // Oppdater Temperatur Label selv .updateTemperatureLabel () // Oppdateringsdato Etikett self.updateDateLabel ()

Etter påkalling av willActivate metode for superklasse, pakker vi ut verdien som er lagret i vær eiendom. For å oppdatere posisjonsetiketten påberoper vi oss setText, passerer i verdien som er lagret i plassering eiendom av vær gjenstand. For å oppdatere temperatur- og datoetikettene, bruker vi to hjelpemetoder. Jeg foretrekker å beholde willActivate metode kort og kortfattet, og enda viktigere, liker jeg ikke å gjenta meg selv.

Før vi ser på disse hjelpemetodene, må vi vite om temperaturen må vises i Celcius eller Fahrenheit. For å løse dette problemet, erklære en eiendom, celcius, av type bool og sett inn initialverdien til ekte.

var celcius: Bool = true

Gjennomføringen av updateTemperatureLabel er lett å forstå. Vi pakker sikkert inn verdien som er lagret i vær og oppdatere temperaturetiketten basert på verdien av celcius. Som du kan se, de to hjelpemetodene til værdata struktur vi opprettet tidligere kommer til nytte.

func updateTemperatureLabel () hvis la været = self.weather if self.celcius temperatureLabel.setText (weather.toCelciusString ()) ellers temperatureLabel.setText (weather.toFahrenheitString ())

Gjennomføringen av updateDateLabel er heller ikke vanskelig. Vi initialiserer en NSDateFormatter eksempel, sett sin dateformat eiendom og konvertere datoen for vær objekt ved å ringe stringFromDate (_ :)dateFormatter gjenstand. Denne verdien brukes til å oppdatere datoetiketten.

func updateDateLabel () var dato: NSDate = NSDate () // Initialize Date Formatter la dateFormattter = NSDateFormatter () // Konfigurer Dato Formatter dateFormattter.dateFormat = "d / MM HH: mm" hvis la været = self.weather date = weather.date // Oppdateringsdato Etikett dateLabel.setText (dateFormattter.stringFromDate (date))

Bygg og kjør programmet for å se resultatet. Brukergrensesnittet skal nå fylles med data fra weather.json.

4. Bytter til Fahrenheit

Dette ser bra ut. Men ville det ikke vært bra hvis vi la til støtte for både Celcius og Fahrenheit? Dette er lett å gjøre siden vi allerede har lagt det meste av grunnen.

Hvis brukerstyrken berører brukergrensesnittet til en brukergrensesnittkontroll, vises en meny. Selvfølgelig virker dette bare hvis en meny er tilgjengelig. La oss se hvordan dette virker.

Åpen Interface.storyboard og legg til en meny til GrensesnittkontrollDokumentoversikt til venstre. Som standard har en meny ett menyelement. Vi trenger to menypunkter, så legg til et annet menyelement på menyen.

Merk at menyen og menyelementene ikke er synlige i brukergrensesnittet. Dette er ikke et problem siden vi ikke kan konfigurere menyenes oppsett. Det vi kan endre er teksten til et menyelement og dets bilde. Du forstår bedre hva det betyr når vi presenterer menyen.

Velg det øverste menyelementet, åpne Attributtsinspektør, sett Tittel til celcius, og Bilde til Aksepterer. Velg det nederste menyelementet og sett Tittel til Fahrenheit og Bilde til Aksepterer.

Deretter åpne InterfaceController.swift Assistent Editor til høyre. Kontroll-Drag fra toppmenyelementet til InterfaceController.swift og opprett en handling som heter toCelcius. Gjenta dette trinnet for det nederste menyelementet, opprett en handling som heter toFahrenheit.

Gjennomføringen av disse handlingene er kort. I toCelcius, vi sjekker om celcius eiendommen er satt til falsk, og hvis det er, setter vi eiendommen til ekte. I toFahrenheit, vi sjekker om celcius eiendommen er satt til ekte, og hvis det er, setter vi eiendommen til falsk.

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

Hvis verdien av celcius endringer, vi må oppdatere brukergrensesnittet. Hvilken bedre måte å oppnå dette ved å implementere en eiendomsobservatør på celcius eiendom. Vi trenger bare å implementere en didSet eiendomsobservatør.

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

Den eneste detalj som er verdt å nevne er at brukergrensesnittet bare oppdateres hvis verdien av celcius endret seg. Oppdatering av brukergrensesnittet er like enkelt som å ringe updateTemperatureLabel. Bygg og kjør WatchKit-programmet i iOS-simulatoren for å teste menyen.

Det er verdt å nevne at iOS-simulatoren etterligner responsen til en fysisk enhet. Hva betyr det? Husk at WatchKit-utvidelsen kjører på en iPhone mens WatchKit-programmet kjører på en Apple Watch. Når brukeren tapper et menyelement, sendes berøringshendelsen over en Bluetooth-tilkobling til iPhone. WatchKit-utvidelsen behandler hendelsen og sender oppdateringer tilbake til Apple Watch. Denne kommunikasjonen er ganske rask, men det er ikke så fort som om både utvidelsen og applikasjonen skulle kjøre på samme enhet. Den korte forsinkelsen etterlignes av iOS Simulator for å hjelpe utviklere å få en ide om ytelse.

Konklusjon

Når du har pakket hodet rundt arkitekturen til et WatchKit-program, blir det mye lettere å forstå mulighetene og begrensningene i den første generasjonen av WatchKit-applikasjoner. I denne opplæringen har vi bare dekket viktigheten av WatchKit-utviklingen. Det er mye mer å oppdage og utforske. Følg med.