I den tidigare handledningen undersökte vi grunden för WatchKit-utvecklingen. Vi skapade ett projekt i Xcode, lade till ett WatchKit-program och skapade ett grundläggande användargränssnitt.
Användargränssnittet för vår WatchKit-applikation visar för närvarande statisk data. Om du inte bor i öknen är det inte särskilt användbart för en väderapplikation. I denna handledning kommer vi att fylla användargränssnittet med data och skapa några åtgärder.
WKInterfaceDate
Innan vi fyller användargränssnittet med data måste vi göra en liten förändring. I den tidigare handledningen lade vi till en WKInterfaceDate
instans till den nedre gruppen för att visa aktuell tid och datum. Det är dock mer användbart att visa tid och datum för de data som vi visar. Anledningen till denna förändring kommer att bli tydlig om några ögonblick.
Öppna Interface.storyboard, ta bort WKInterfaceDate
instans i den nedre gruppen och ersätt den med a WKInterfaceLabel
exempel. Ange etikettens Bredd tillskriva Relativt till behållaren och etiketten Inriktning till högerinriktad.
För att uppdatera användargränssnittet med dynamiska data behöver vi skapa några uttag i InterfaceController
klass. Öppna storyboardet i huvudredigeraren och InterfaceController.swift i Assistent Editor till höger. Välj den övre etiketten i den första gruppen och Ctrl-dra från etiketten till InterfaceController
klass för att skapa ett uttag. Namn utloppet locationLabel
.
Upprepa dessa steg för de andra etiketterna, namngivna dem temperatureLabel
och dateLabel
respektive. Det här är vad InterfaceController
klassen ska se ut när du är klar.
importera WatchKit import Foundation class InterfaceController: WKInterfaceController @IBOutlet weak var dateLabel: WKInterfaceLabel! @IBOutlet svag var locationLabel: WKInterfaceLabel! @IBOutlet svag var temperatureLabel: WKInterfaceLabel! åsidosätta func awakeWithContext (context: AnyObject?) super.awakeWithContext (context) åsidosätta func willActivate () // Denna metod kallas när watch view controller är på väg att vara synlig för användaren super.willActivate () åsidosätta func didDeactivate ) // Den här metoden heter när Watch View Controller inte längre är synlig super.didDeactivate ()
Nu kan det vara en bra tid att ta en närmare titt på genomförandet av InterfaceController
klass. I den tidigare handledningen nämnde jag det InterfaceController
ärver från WKInterfaceController
. Vid första anblicken kan det verka som om a WKInterfaceController
Exempel beter sig som a UIViewController
exempel, men vi lärde oss också i den tidigare handledningen att det finns ett antal viktiga skillnader.
För att hjälpa oss har Xcode befolket InterfaceController
klass med tre överdrivna metoder. Det är viktigt att förstå när varje metod åberopas och vad den kan eller ska användas till.
awakeWithContect (_ :)
I awakeWithContext (_ :)
Metod, du ställer in och initierar gränssnittskontrollen. Du kanske undrar hur det skiljer sig från i det
metod. De awakeWithContext (_ :)
Metoden åberopas efter att gränssnittsregulatorn initialiserats. Metoden accepterar en parameter, ett kontextobjekt som tillåter gränssnittsstyrare att skicka information till varandra. Detta är det rekommenderade tillvägagångssättet för att skicka information över scener, det vill säga gränssnittsregulatorer.
willActivate
De willActivate
Metoden liknar viewWillAppear (_ :)
metod för UIViewController
klass. De willActivate
Metoden åberopas innan användargränssnittet för gränssnittsstyrenheten presenteras för användaren. Det är perfekt för tweaking av användargränssnittet innan det presenteras för användaren.
didDeactivate
De didDeactivate
Metod är motstycke till willActivate
metod och åberopas när gränssnittskontrollens scen har tagits bort. En eventuell uppringningskod går in i denna metod. Denna metod liknar viewDidDisappear (_ :)
metod som hittades i UIViewController
klass.
Med ovanstående kan vi börja ladda data och uppdatera användargränssnittet för vår WatchKit-applikation. Låt oss börja med att ladda väderdata.
Du kanske tror att nästa steg innebär ett API-samtal till en väderstjänst, men det är inte så. Om vi byggde ett iOS-program skulle du ha rätt. Vi skapar dock ett WatchKit-program.
Det rekommenderas inte att göra komplexa API-samtal för att hämta data för att fylla i användargränssnittet för en WatchKit-applikation. Även om Apple inte uttryckligen nämner detta i dokumentationen, nämnde en Apple-ingenjör denna oskrivna bästa praxis i Apples utvecklarforum.
WatchKit-programmet är en del av ett iOS-program och det är iOS-programmet som ansvarar för att hämta data från en fjärrbackend. Det finns flera tillvägagångssätt som vi kan vidta för att göra detta, att hämta bakgrund är ett bra val. I denna handledning kommer vi dock inte att fokusera på den aspekten.
Istället lägger vi till dummy-data i buntet i WatchKit-tillägget och laddar det i awakeWithContext (_ :)
metod vi diskuterade tidigare.
Skapa en tom fil genom att välja Ny> Fil ... från Fil meny. Välja Tömma från iOS> Annat avsnitt och namnge filen weather.json. Dubbelkontrollera att du lägger till filen i filen RainDrop WatchKit Extension. Utse inte denna lilla men viktiga detalj. Bifoga filen med följande data.
"platser": ["plats": "Cupertino", "temperatur": 24, "tidsstämpel": 1427429751, "plats": "London", "temperatur": 11, "tidsstämpel": 1427429751 "Plats": "Paris", "Temperatur": 9, "Tidstämpel": 1427429751, "Plats": "Bryssel", "Temperatur": 11, "Tidstämpel": 1427429751]
Att dela data mellan iOS-programmet och WatchKit-programmet är ett viktigt ämne. Men denna handledning fokuserar på att få ditt första WatchKit-program igång. I en framtida handledning kommer jag att fokusera på att dela data mellan en iOS och ett WatchKit-program.
Även om vi inte kommer att täcka delning av data i den här handledningen är det viktigt att veta att iOS-programmet och WatchKit-tillägget inte delar en sandlåda. Båda målen har sin egen sandlåda och det gör det att dela data mindre trivial än det verkar.
För att dela data mellan iOS och WatchKit-programmet måste du utnyttja appgrupper. Men det är ett ämne för en framtida handledning.
Swift är ett bra språk, men vissa uppgifter är enklare i mål-C än de är i Swift. Hantering av JSON är till exempel en sådan uppgift. För att göra denna uppgift enklare har jag valt att utnyttja det populära SwiftyJSON-biblioteket.
Ladda ner förvaret från GitHub, pakka ut arkivet och lägg till SwiftyJSON.swift till RainDrop WatchKit Extension grupp. Den här filen finns i Källa Arkivets mapp. Dubbelkontrollera det SwiftyJSON.swift läggs till RainDrop WatchKit Extension mål.
WeatherData
För att göra det enklare att arbeta med de väderdata som lagras i weather.json, Vi ska skapa en struktur som heter WeatherData. Välj Ny> Fil ... från de Fil meny, välj Swift File från iOS> Källa avsnitt och namnge filen WeatherData. Kontrollera att filen har lagts till i RainDrop WatchKit Extension mål.
Genomförandet av WeatherData
strukturen är kort och enkel. Strukturen definierar tre konstanta egenskaper, datum
, plats
, och temperatur
.
import Foundation struktur WeatherData låt datum: NSDate låt plats: String låt temperatur: Double
Eftersom temperaturvärdet på weather.json är i Celcius implementerar vi också en beräknad egendom fahrenheit
för enkel konvertering mellan Celcius och Fahrenheit.
var fahrentheit: Dubbel returtemperatur * (9/5) + 32
Vi definierar också två hjälpar metoder toCelciusString
och toFahrenheitString
för att göra formateringstemperaturerna enklare. Älskar du inte Swifts stränginterpolation?
func toCelciusString () -> String return "\ (temperatur) ° C" func toFahrenheitString () -> String return "\ (fahrentheit) ° F"
Som jag sa, genomförandet av WeatherData
strukturen är kort och enkel. Så här ska genomförandet se ut.
importera Foundation Struct WeatherData låt datum: NSDate låt plats: String Låt temperatur: Dubbel var fahrentheit: Dubbel Returtemperatur * (9/5) + 32 Func toCelciusString () -> String Retur "\ (Temperatur) ° C" func toFahrenheitString () -> String return "\ (fahrentheit) ° F"
Innan vi laddar data från weather.json, Vi måste förklara en egendom för lagring av väderdata. Egendomen, weatherData
, är av typ [WeatherData]
och kommer att innehålla innehållet i weather.json som fall av WeatherData
strukturera.
var weatherData: [WeatherData] = []
För enkel användning, förklarar vi också en beräknad egendom, väder
, som ger oss tillgång till första objektet i weatherData
array. Det är uppgifterna om detta WeatherData
exempel som vi kommer att visa i gränssnittskontrollen. Kan du gissa varför vi måste förklara väder
egendom som tillval?
var väder: WeatherData? return weatherData.first
Vi laddar data från weather.json i awakeWithContext (_ :)
metod. För att hålla implementeringen ren, anropar vi en hjälparmetod som heter loadWeatherData
.
åsidosätta func awakeWithContext (context: AnyObject?) super.awakeWithContext (context) // Ladda väderdata loadWeatherData ()
Genomförandet av loadWeatherData
är förmodligen det mest skrämmande kodbiten vi ser i den här handledningen. Som jag sa är parsing JSON inte trivial i Swift. Lyckligtvis gör SwiftyJSON det mesta av det tunga för oss.
func loadWeatherData () let path = NSBundle.mainBundle (). pathForResource ("weather", ofType: "json") om släpp path = path let data = NSData (contentOfFile: path) om låt data = data let weatherData = JSON (data: data) låt platser = weatherData ["locations"]. Array om låt platser = platser för plats på platser let timestamp = location ["timestamp"]. Dubbel! låt datum = NSDate (timeIntervalSinceReferenceDate: timestamp) låt modell = WeatherData (datum: datum, plats: plats ["plats"]. sträng !, temperatur: plats ["temperatur"]. dubbel!) self.weatherData.append (modell)
Vi får vägen till weather.json och ladda dess innehåll som en NSData
objekt. Vi använder SwiftyJSON för att analysera JSON, som passerar in i NSData
objekt. Vi får en hänvisning till matrisen för nyckeln platser och slinga över varje plats.
Vi normaliserar väderdata genom att konvertera tidstämpeln till en NSDate
instans och initiera a WeatherData
objekt. Slutligen lägger vi till WeatherData
protestera mot weatherData
array.
Jag hoppas att du håller med om att genomförandet inte är så svårt. Eftersom Swift tvingar oss att göra ett antal kontroller, ser genomförandet ut mer komplicerat än det faktiskt är.
Med väderinformationen redo att användas är det dags att uppdatera användargränssnittet. Som jag förklarade tidigare måste uppdatering av användargränssnittet hända i willActivate
metod. Låt oss ta en titt på genomförandet av denna metod.
åsidosätta func willActivate () // Den här metoden kallas när vaktvisningskontrollen är synlig för användaren super.willActivate () om låt väder = self.weather locationLabel.setText (weather.location) // Uppdateringstemperaturetikett själv .updateTemperatureLabel () // Uppdateringsdatum Etikett self.updateDateLabel ()
Efter att ha åberopat willActivate
Metoden för superklassen, vi paketerar det värde som lagrats i väder
fast egendom. För att uppdatera platsetiketten åberopar vi setText
, passerar i det värde som lagrats i plats
egenskapen hos väder
objekt. För att uppdatera temperatur- och datumetiketterna åberopar vi två hjälpar metoder. Jag föredrar att hålla willActivate
metod kortfattad och kortfattad, och viktigare, jag gillar inte att upprepa mig själv.
Innan vi tittar på dessa hjälpmetoder måste vi veta om temperaturen måste visas i Celcius eller Fahrenheit. För att lösa detta problem, förklara en egendom, celcius
, av typ Bool
och ställa in dess ursprungliga värde till Sann
.
var celcius: Bool = true
Genomförandet av updateTemperatureLabel
är lätt att förstå. Vi paketerar säkert det värde som lagrats i väder
och uppdatera temperaturmärket baserat på värdet på celcius
. Som du kan se, två hjälpar metoder av WeatherData
struktur vi skapade tidigare kommer till nytta.
func updateTemperatureLabel () om låt väder = self.weather if self.celcius temperatureLabel.setText (weather.toCelciusString ()) annars temperatureLabel.setText (weather.toFahrenheitString ())
Genomförandet av updateDateLabel
är inte heller svårt. Vi initierar en NSDateFormatter
Exempel, sätt dess datumformat
egendom och konvertera datumet för väder
objekt genom att ringa stringFromDate (_ :)
på dateFormatter
objekt. Detta värde används för att uppdatera datumetiketten.
func updateDateLabel () var datum: NSDate = NSDate () // Initialize Date Formatter låt dateFormattter = NSDateFormatter () // Konfigurera datum Formatera dateFormattter.dateFormat = "d / MM HH: mm" om låt väder = self.weather date = weather.date // Uppdateringsdatum Etikett dateLabel.setText (datumFormattter.stringFromDate (datum))
Bygg och kör programmet för att se resultatet. Användargränssnittet bör nu fyllas med data från weather.json.
Det ser bra ut. Men skulle det inte vara bra om vi lagt till stöd för både Celcius och Fahrenheit? Det här är lätt att göra eftersom vi redan har lagt det mesta av grunden.
Om användarkraften berör användargränssnittet för en användargränssnittskontroll, visas en meny. Självklart fungerar det bara om en meny är tillgänglig. Låt oss se hur det här fungerar.
Öppna Interface.storyboard och lägg till en meny till Gränssnittskontroller i Dokumentbeskrivning till vänster. Som standard har en meny ett menyalternativ. Vi behöver två menyalternativ så lägg till ett annat menyalternativ på menyn.
Observera att menyn och menyalternativen inte är synliga i användargränssnittet. Detta är inte ett problem eftersom vi inte kan konfigurera menyns layout. Vad vi kan ändra är texten på ett menyobjekt och dess bild. Du förstår bättre vad det innebär när vi presenterar menyn.
Välj det översta menyalternativet, öppna Attribut Inspector, uppsättning Titel till Celcius, och Bild till Acceptera. Välj det nedre menyalternativet och ställ in Titel till fahrenheit och Bild till Acceptera.
Nästa, öppna InterfaceController.swift i Assistent Editor till höger. Ctrl-dra från översta menyalternativet till InterfaceController.swift och skapa en åtgärd som heter toCelcius
. Upprepa det här steget för det nedre menyobjektet, skapa en åtgärd som heter toFahrenheit
.
Genomförandet av dessa åtgärder är kort. I toCelcius
, vi kontrollerar om celcius
fastigheten är inställd på falsk
, och om det är så ställer vi fastigheten till Sann
. I toFahrenheit
, vi kontrollerar om celcius
fastigheten är inställd på Sann
, och om det är så ställer vi fastigheten till falsk
.
@IBAction func toCelcius () if! Self.celcius self.celcius = true @IBAction func toFahrenheit () om self.celcius self.celcius = false
Om värdet av celcius
ändringar måste vi uppdatera användargränssnittet. Vilket bättre sätt att uppnå detta genom att genomföra en fastighetsobservatör på celcius
fast egendom. Vi behöver bara genomföra en didSet
fastighetsobservatör.
var celcius: Bool = true didSet om celcius! = oldValue updateTemperatureLabel ()
Den enda detalj som är värt att nämna är att användargränssnittet bara uppdateras om värdet av celcius
förändrade sig. Uppdatering av användargränssnittet är lika enkelt som att ringa updateTemperatureLabel
. Bygg och kör WatchKit-programmet i iOS-simulatorn för att testa menyn.
Det är värt att nämna att iOS-simulatorn efterliknar en fysisk enhetens lyhördhet. Vad betyder det? Kom ihåg att WatchKit-tillägget körs på en iPhone medan WatchKit-programmet körs på en Apple Watch. När användaren knackar på ett menyalternativ skickas kontakthändelsen via en Bluetooth-anslutning till iPhone. WatchKit-förlängningen behandlar händelsen och skickar uppdateringar tillbaka till Apple Watch. Kommunikationen är ganska snabb, men det är inte så snabbt som om både tillägg och applikation skulle köras på samma enhet. Den korta fördröjningen efterliknas av IOS Simulator för att hjälpa utvecklare att få en uppfattning om prestanda.
När du har förstört ditt huvud kring arkitekturen i ett WatchKit-program blir det mycket lättare att förstå möjligheterna och begränsningarna i den första generationen WatchKit-applikationer. I den här handledningen har vi bara täckt de viktigaste aspekterna av WatchKit-utvecklingen. Det finns mycket mer att upptäcka och utforska. Håll dig igång.