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.
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.
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.
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 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.
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.
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"
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.json i awakeWithContext (_ :)
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.
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 (_ :)
på 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.
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 Grensesnittkontroll i Dokumentoversikt 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 i 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.
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.