Votre première application WatchKit Interaction utilisateur

Dans le précédent tutoriel, nous avons exploré les principes fondamentaux du développement de WatchKit. Nous avons créé un projet dans Xcode, ajouté une application WatchKit et créé une interface utilisateur de base..

L'interface utilisateur de notre application WatchKit affiche actuellement des données statiques. Sauf si vous vivez dans le désert, ce n'est pas très utile pour une application météo. Dans ce tutoriel, nous allons renseigner l'interface utilisateur avec des données et créer quelques actions..

1. Mise à jour de l'interface utilisateur

Étape 1: remplacement WKInterfaceDate

Avant de renseigner l'interface utilisateur avec des données, nous devons effectuer un petit changement. Dans le tutoriel précédent, nous avons ajouté un WKInterfaceDate instance au groupe du bas pour afficher l'heure et la date actuelles. Il serait cependant plus utile d’afficher l’heure et la date des données que nous affichons. La raison de ce changement deviendra claire dans quelques instants.

Ouvrir Interface.storyboard, retirer le WKInterfaceDate exemple dans le groupe du bas et le remplacer par un WKInterfaceLabel exemple. Définir l'étiquette Largeur attribuer à Relatif au conteneur et de l'étiquette Alignement à droite alignée.

Étape 2: Ajout de points de vente

Pour mettre à jour l’interface utilisateur avec des données dynamiques, nous devons créer quelques points de vente dans le répertoire. InterfaceController classe. Ouvrez le storyboard dans l'éditeur principal et InterfaceController.swift dans le Assistant rédacteur sur la droite. Sélectionnez l'étiquette du haut dans le premier groupe et Control-Drag de l'étiquette à la InterfaceController classe pour créer un point de vente. Nommez le point de vente locationLabel.

Répétez ces étapes pour les autres étiquettes, en les nommant. temperatureLabel et dateLabel respectivement. C'est ce que le InterfaceController la classe devrait ressembler quand vous avez fini.

import WatchKit import Classe Foundation InterfaceController: WKInterfaceController @IBOutlet faible var dateLabel: WKInterfaceLabel! @IBOutlet faible var locationLabel: WKInterfaceLabel! @IBOutlet faible var temperatureLabel: WKInterfaceLabel! Remplacer func awakeWithContext (contexte: AnyObject?) super.awakeWithContext (context) remplacer func willActivate () // Cette méthode est appelée lorsque le contrôleur d'affichage de vue est sur le point d'être visible par l'utilisateur super.willActivate () override func didDeactivate ( ) // Cette méthode est appelée lorsque le contrôleur d'affichage de la vue n'est plus visible. Super.didDeactivate ()

Le moment est peut-être venu d’examiner de plus près la mise en œuvre de la InterfaceController classe. Dans le tutoriel précédent, j'ai mentionné que InterfaceController hérite de WKInterfaceController. À première vue, cela peut sembler être un WKInterfaceController par exemple se comporte comme un UIViewController exemple, mais nous avons également appris dans le tutoriel précédent qu’il existe un certain nombre de différences essentielles.

Pour nous aider, Xcode a rempli le InterfaceController classe avec trois méthodes substituées. Il est important de comprendre quand chaque méthode est invoquée et à quoi elle peut ou devrait servir..

awakeWithContect (_ :)

dans le awakeWithContext (_ :) méthode, vous configurez et initialisez le contrôleur d’interface. Vous vous demandez peut-être en quoi cela diffère de la init méthode. le awakeWithContext (_ :) La méthode est invoquée après l’initialisation du contrôleur d’interface. La méthode accepte un paramètre, un objet de contexte qui permet aux contrôleurs d'interface de se transmettre des informations. C’est l’approche recommandée pour transmettre des informations d’une scène à l’autre, c’est-à-dire des contrôleurs d’interface..

willActivate

le willActivate la méthode est similaire à la viewWillAppear (_ :) méthode du UIViewController classe. le willActivate Cette méthode est appelée avant que l'interface utilisateur du contrôleur d'interface ne soit présentée à l'utilisateur. Idéal pour peaufiner l'interface utilisateur avant sa présentation à l'utilisateur.

didDésactiver

le didDésactiver méthode est la contrepartie de la willActivate méthode et est invoquée lorsque la scène du contrôleur d'interface a été supprimée. Tout code de nettoyage va dans cette méthode. Cette méthode est similaire à la viewDidDisappear (_ :) méthode trouvée dans le UIViewController classe.

Compte tenu de ce qui précède, nous pouvons commencer à charger des données et à mettre à jour l'interface utilisateur de notre application WatchKit. Commençons par le chargement des données météorologiques.

2. Chargement des données météorologiques

Les meilleures pratiques

Vous pensez peut-être que la prochaine étape implique un appel d'API à un service météo, mais ce n'est pas le cas. Si nous construisions une application iOS, vous auriez raison. Cependant, nous créons une application WatchKit.

Il n'est pas recommandé de faire des appels d'API complexes pour extraire des données afin de remplir l'interface utilisateur d'une application WatchKit. Même si Apple ne le mentionne pas explicitement dans la documentation, un ingénieur Apple a mentionné cette meilleure pratique non écrite dans les forums de développeurs Apple..

L'application WatchKit fait partie d'une application iOS. Il s'agit de l'application iOS chargée de récupérer les données d'un serveur distant. Il existe plusieurs approches que nous pouvons adopter pour ce faire, la récupération d’arrière-plan étant un bon choix. Dans ce tutoriel, cependant, nous n'allons pas nous concentrer sur cet aspect.

Au lieu de cela, nous allons ajouter des données factices à l'ensemble de l'extension WatchKit et les charger dans la awakeWithContext (_ :) méthode nous avons discuté plus tôt.

Créez un fichier vierge en sélectionnant Nouveau> Fichier…  du Fichier menu. Choisir Vide du iOS> Autre section et nommez le fichier weather.json. Vérifiez que vous ajoutez le fichier au RainDrop WatchKit Extension. Ne négligez pas ce détail petit mais important. Remplir le fichier avec les données suivantes.

"locations": ["location": "Cupertino", "temperature": 24, "timestamp": 1427429751, "location": "Londres", "temperature": 11, "timestamp": 1427429751, "localisation": "Paris", "température": 9, "horodatage": 1427429751, "localisation": "Bruxelles", "température": 11, "horodatage": 1427429751]

Partage de données

Le partage de données entre l'application iOS et l'application WatchKit est un sujet important. Cependant, ce tutoriel se concentre sur la mise en service de votre première application WatchKit. Dans un prochain tutoriel, je me concentrerai sur le partage de données entre un iOS et une application WatchKit.

Même si nous ne couvrirons pas le partage de données dans ce tutoriel, il est important de savoir que l'application iOS et l'extension WatchKit ne partagent pas un bac à sable. Les deux cibles ont leur propre bac à sable et c'est ce qui rend le partage de données moins trivial qu'il n'y parait.

Pour partager des données entre iOS et l'application WatchKit, vous devez exploiter les groupes d'applications. Mais c'est un sujet pour un futur tutoriel.

Étape 1: Ajout de SwiftyJSON

Swift est un excellent langage, mais certaines tâches sont plus simples dans Objective-C que dans Swift. La gestion de JSON, par exemple, est l’une de ces tâches. Pour faciliter cette tâche, j'ai choisi de tirer parti de la célèbre bibliothèque SwiftyJSON..

Téléchargez le référentiel depuis GitHub, décompressez l'archive et ajoutez SwiftyJSON.swift au RainDrop WatchKit Extension groupe. Ce fichier est situé dans le La source dossier de l'archive. Vérifiez que SwiftyJSON.swift est ajouté le RainDrop WatchKit Extension cible.

Étape 2: mise en œuvre WeatherData

Pour faciliter le travail avec les données météorologiques stockées dans weather.json, nous allons créer une structure nommée WeatherData. Sélectionner Nouveau> Fichier… de la Fichier menu, choisissez Fichier rapide du iOS> Source section, et nommez le fichier WeatherData. Assurez-vous que le fichier est ajouté à la RainDrop WatchKit Extension cible.

La mise en œuvre de la WeatherData la structure est courte et simple. La structure définit trois propriétés constantes, rendez-vous amoureux, emplacement, et Température.

importation de la structure de base WeatherData date: NSDate location: String température: Double

Parce que la valeur de température de weather.json est en Celcius, nous implémentons également une propriété calculée Fahrenheit pour une conversion facile entre Celsius et Fahrenheit.

var fahrentheit: Double température de retour * (9/5) + 32

Nous définissons également deux méthodes d'assistance toCelciusString et toFahrenheitString pour faciliter le formatage des valeurs de température. Vous n'aimez pas l'interpolation de chaîne de Swift?

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

Comme je le disais, la mise en œuvre de la WeatherData la structure est courte et simple. Voici à quoi devrait ressembler l'implémentation.

Importer la structure de base WeatherData date: NSDate location: Chaîne température: Double valeur de retour: Double température de retour * (9/5) + 32 func toCelciusString () -> Chaîne retour "\ (température) ° C"  func toFahrenheitString () -> String return "\ (fahrentheit) ° F"

Étape 3: Chargement des données

Avant de charger les données de weather.json, nous devons déclarer une propriété pour stocker les données météorologiques. La propriété, weatherData, est de type [WeatherData] et contiendra le contenu de weather.json comme des exemples de WeatherData structure.

var weatherData: [WeatherData] = []

Pour plus de facilité, nous déclarons également une propriété calculée, Météo, qui nous donne accès au premier élément de la weatherData tableau. Ce sont les données de cette WeatherData exemple que nous afficherons dans le contrôleur d'interface. Pouvez-vous deviner pourquoi nous devons déclarer le Météo propriété en option?

var météo: WeatherData? return weatherData.first

Nous chargeons les données de weather.json dans le awakeWithContext (_ :) méthode. Pour garder l'implémentation propre, nous appelons une méthode d'assistance nommée loadWeatherData.

remplacer func awakeWithContext (contexte: AnyObject?) super.awakeWithContext (context) // Chargement des données météo loadWeatherData ()

L'implémentation de loadWeatherData est probablement l'extrait de code le plus décourageant que nous verrons dans ce tutoriel. Comme je l'ai dit, l'analyse de JSON n'est pas anodine dans Swift. Heureusement, SwiftyJSON fait le gros du travail pour nous.

func loadWeatherData () let path = NSBundle.mainBundle (). pathForResource ("weather", ofType: "json") si let path = path let data = NSData (contentsOfFile: chemin) si let data = data let weatherData = JSON (data: data) let locations = weatherData ["locations"]. Array if let localisations = locations pour localiser des localisations let timestamp = location ["timestamp"]. Double! let date = NSDate (timeIntervalSinceReferenceDate: horodatage) let model = WeatherData (date: date, emplacement: emplacement ["emplacement"]. string !, temperature: emplacement ["température"]. double!) self.weatherData.append (modèle) 

Nous obtenons le chemin pour weather.json et charger son contenu en tant que NSData objet. Nous utilisons SwiftyJSON pour analyser le JSON, en passant le NSData objet. On obtient une référence au tableau pour la clé Emplacements et boucle sur chaque emplacement.

Nous normalisons les données météorologiques en convertissant l’horodatage en un NSDate par exemple et initialiser un WeatherData objet. Enfin, nous ajoutons le WeatherData objecter à la weatherData tableau.

J'espère que vous conviendrez que la mise en œuvre n'est pas si difficile. Parce que Swift nous oblige à effectuer un certain nombre de vérifications, la mise en œuvre semble plus complexe qu'elle ne l'est réellement..

3. Remplir l'interface utilisateur

Avec les données météorologiques prêtes à être utilisées, il est temps de mettre à jour l'interface utilisateur. Comme je l’ai expliqué précédemment, la mise à jour de l’interface utilisateur doit se faire dans le willActivate méthode. Regardons l'implémentation de cette méthode.

override func willActivate () // Cette méthode est appelée lorsque le contrôleur d'affichage de la vue est sur le point d'être visible par l'utilisateur super.willActivate () si let weather = self.weather locationLabel.setText (weather.location) // Update Update Label lui-même .updateTemperatureLabel () // Libellé de la date de mise à jour self.updateDateLabel ()

Après avoir invoqué le willActivate méthode de la super-classe, nous déballons la valeur stockée dans le Météo propriété. Pour mettre à jour l'étiquette d'emplacement, nous appelons Définir le texte, en passant la valeur stockée dans le emplacement propriété du Météo objet. Pour mettre à jour les étiquettes de température et de date, nous appelons deux méthodes auxiliaires. Je préfère garder le willActivate méthode courte et concise, et, plus important encore, je n'aime pas me répéter.

Avant d'examiner ces méthodes d'assistance, nous devons savoir si la température doit être affichée en degrés Celsius ou Fahrenheit. Pour résoudre ce problème, déclarez une propriété, celcius, de type Bool et définir sa valeur initiale à vrai.

var celcius: Bool = true

L'implémentation de updateTemperatureLabel est facile à comprendre. Nous décompressons en toute sécurité la valeur stockée dans Météo et mettre à jour l'étiquette de température en fonction de la valeur de celcius. Comme vous pouvez le constater, les deux méthodes d’aide du WeatherData la structure que nous avons créée précédemment est très utile.

func updateTemperatureLabel () si laissez weather = self.weather si self.celcius temperatureLabel.setText (weather.toCelciusString ()) else temperatureLabel.setText (weather.toFahrenheitString ())

L'implémentation de updateDateLabel ce n'est pas difficile non plus. Nous initialisons un NSDateFormatter par exemple, définissez son format de date propriété, et convertir la date de la Météo objet en appelant stringFromDate (_ :) sur le dateFormatter objet. Cette valeur est utilisée pour mettre à jour l'étiquette de date.

func updateDateLabel () var date: NSDate = NSDate () // Initialise le formateur de date, laissez dateFormattter = NSDateFormatter () // Configure le formateur de date dateFormattter.dateFormat = "d / MM HH: mm" si le temps est passé = self.weather date = weather.date // Date de mise à jour du libellé dateLabel.setText (dateFormattter.stringFromDate (date))

Générez et exécutez l'application pour voir le résultat. L’interface utilisateur doit maintenant être renseignée avec les données de weather.json.

4. Passage en Fahrenheit

Cela semble bon. Mais ne serait-il pas formidable d'ajouter un support pour Celcius et Fahrenheit? C'est facile à faire puisque nous avons déjà préparé la plupart des travaux préparatoires..

Si l'utilisateur touche de force l'interface utilisateur d'un contrôleur d'interface utilisateur, un menu s'affiche. Bien sûr, cela ne fonctionne que si un menu est disponible. Voyons comment cela fonctionne.

Ouvrir Interface.storyboard et ajouter un menu au Contrôleur d'interface dans le Sommaire du document sur la gauche. Par défaut, un menu a un élément de menu. Nous avons besoin de deux éléments de menu, alors ajoutez un autre élément de menu au menu..

Notez que le menu et ses éléments de menu ne sont pas visibles dans l'interface utilisateur. Ce n'est pas un problème car nous ne pouvons pas configurer la disposition du menu. Ce que nous pouvons changer, c'est le texte d'un élément de menu et son image. Vous comprendrez mieux ce que cela signifie lorsque nous présentons le menu.

Sélectionnez l'élément du menu supérieur, ouvrez le Inspecteur d'attributs, ensemble Titre à Celcius, et Image à Acceptez. Sélectionnez l'élément de menu du bas et définissez Titre à Fahrenheit et Image à Acceptez.

Ensuite, ouvrez InterfaceController.swift dans le Assistant rédacteur sur la droite. Control-Drag de l'élément de menu supérieur à InterfaceController.swift et créer une action nommée toCelcius. Répétez cette étape pour l’élément de menu inférieur en créant une action nommée toFahrenheit.

La mise en œuvre de ces actions est courte. Dans toCelcius, nous vérifions si le celcius la propriété est définie sur faux, et, si c'est le cas, nous définissons la propriété sur vrai. Dans toFahrenheit, nous vérifions si le celcius la propriété est définie sur vrai, et, si c'est le cas, nous définissons la propriété sur faux.

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

Si la valeur de celcius changements, nous devons mettre à jour l'interface utilisateur. Quel meilleur moyen d’y parvenir en mettant en place un observateur de la propriété sur le celcius propriété. Nous avons seulement besoin de mettre en place un didSet observateur immobilier.

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

Le seul détail à noter est que l’interface utilisateur n’est mise à jour que si la valeur de celcius a changé. Mettre à jour l'interface utilisateur est aussi simple que d'appeler updateTemperatureLabel. Construire et exécuter l'application WatchKit dans le simulateur iOS pour tester le menu.

Il est à noter que le simulateur iOS imite la réactivité d'un périphérique physique. Qu'est-ce que ça veut dire? N'oubliez pas que l'extension WatchKit s'exécute sur un iPhone, tandis que l'application WatchKit s'exécute sur une Apple Watch. Lorsque l'utilisateur appuie sur un élément de menu, l'événement tactile est envoyé via une connexion Bluetooth à l'iPhone. L'extension WatchKit traite l'événement et renvoie les mises à jour à l'Apple Watch. Cette communication est rapide, mais pas aussi rapide que si l’extension et l’application devaient fonctionner sur le même appareil. Le simulateur iOS imite ce court délai pour aider les développeurs à se faire une idée de la performance..

Conclusion

Une fois que vous avez compris l'architecture d'une application WatchKit, il est beaucoup plus facile de comprendre les possibilités et les limites de la première génération d'applications WatchKit. Dans ce didacticiel, nous n'avons abordé que l'essentiel du développement de WatchKit. Il y a beaucoup plus à découvrir et à explorer. Restez à l'écoute.