Il y a 8 ans -
Temps de lecture 7 minutes
WatchKit: Episode II – Codez une application Apple Watch en Swift
Dans notre précédent article nous vous avions présenté les APIs de WatchKit, le kit de développement pour Apple Watch. Aujourd’hui, nous allons vous expliquer pas-à-pas comment coder une application Swift dédiée aux Apple Watch.
Vous y apprendrez comment réaliser une interface graphique pour une Apple Watch, partager du code entre application iOS et Apple Watch, ainsi que configurer l’UI depuis un jeu de données.
Le projet : codez une application Apple Watch en Swift
Le but de ce tutoriel est de créer une application permettant d’afficher des données relatives à une station de ski. L’interface se composera de deux vues (ou scènes) :
- La première affichera une liste de stations de ski à l’intérieur d’un Table
- La seconde vue affichera les informations relatives à la station de ski sélectionnée par l’utilisateur
Si vous souhaitez tester l’application ou comparer votre code pendant votre avancée dans l’exercice, libre à vous de le récupérer depuis notre repository Github.
Pour réaliser l’exercice, ouvrez Xcode et créez un projet vierge nommé XebiaSkiDemo. Ensuite, ajoutez une nouvelle target pour avoir le support Apple Watch : File > New… > Target… > Apple Watch > Watch App
Vous remarquerez qu’en réalité Xcode a créé 2 nouvelles targets:
- XebiaSkiDemo WatchKit Extension
- XebiaSkiDemo Watch App
Pour connaître le rôle de chacune d’entre-elles n’hésitez pas à aller (re)lire notre article sur les APIs de WatchKit.
Ces deux targets vont nous donner les étapes à suivre pour la réalisation de l’application:
- D’abord la réalisation de l’UI dans XebiaSkiDemo Watch App (Watch App dans la suite de l’article)
- Puis le code de logique associé, dans XebiaSkiDemo WatchKit Extension (WatchKit Extension dans la suite de l’article)
1. Watch App
Le but de cette section est de réaliser l’UI pour les deux scènes de notre application:
- La liste des stations de ski
- Les informations d’une station de ski
Ces deux scènes sont à réaliser dans le storyboard contenu dans Watch App. Le travail est laissé comme exercice au lecteur. Voici cependant quelques conseils:
- La première vue est une liste. N’hésitez donc pas à utiliser des objets Table (WKInterfaceTable)
- La seconde vue est plus complexe : pensez à utiliser des Group pour pouvoir aligner les éléments (notamment horizontalement)
N’hésitez pas à aller voir notre exemple en cas de besoin ou à regarder le screenshot ci-dessous de notre storyboard.
Une fois terminée la première partie, vous aurez une UI prête à l’emploi. Ou presque. En effet, aucune donnée n’y sera affichée. Vous allez résoudre cet affront avec l’étape 2 : l’extension !
2.1 Prélude à l’extension : Cocoa Touch Framework
Comme déjà évoqué, WatchKit Extension contient toute la logique associé à Watch App. Cependant, dans la plupart des cas votre application iOS et la WatchKit Extension vont posséder des classes communes tels que les modèles, la couche réseau ou encore des catégories utilitaires.
Afin d’éviter de dupliquer cette logique, dans le respect du principe DRY (Don’t Repeat Yourself), il faudra partager un module parmi deux targets. Pour ce faire, il est nécessaire de mettre en place un framework. La création des frameworks est possible depuis Xcode 6 en générant une target de type « Cocoa Touch Framework » qui devra ensuite être ajoutée en tant que dépendance dans les autres targets de notre projet.
Pour créer le framework, dans le menu sélectionnez File > New… > Target… > Framework&Library > Cocoa Touch Framework. Le nom choisi sera XebiaSkiDemoFramework
Ensuite créez une classe, nommée SkiResort, afin de représenter les stations de ski.
[java]public class SkiResort: NSObject {
public var name: String
public var photoURL: NSURL
public var temperature: Int
// L’implémentation du ctor est laissé comme exercice
}[/java]
Puis créez la classe SkiResortDataSource. Pour éviter d’implémenter des Web Services, qui ne sont pas le but de cet exercice, celle-ci va vous renvoyer une liste statique de stations de type SkiResort.
[java]public class SkiResortDataSource {
var allObjects: Array<SkiResort>
public init() {
self.allObjects = [
SkiResort(name: "Arcabulle", photoURL: NSURL(string: "http://www.trinum.com/ibox/ftpcam/les-arcs_arcabulle.jpg")!, temperature: 5),
SkiResort(name: "Arcs 1600 Pistes", photoURL: NSURL(string: "http://static1.lesarcsnet.com/image_uploader/webcam/large/lesarcs-1600-cam.jpg")!, temperature: -2),
SkiResort(name: "Vanoise Express", photoURL: NSURL(string: "http://trinum.com/ibox/ftpcam/Peisey-Vallandry_vanoise-expresse.jpg")!, temperature: 4),
SkiResort(name: "Arc 1950 Village", photoURL: NSURL(string: "http://www.trinum.com/ibox/ftpcam/arc-1950-haut-village.jpg")!, temperature: 0)
]
}
public var count: Int {
get {
return self.allObjects.count
}
}
public subscript(index: Int) -> SkiResort {
return self.allObjects[index]
}
}[/java]
La dernière classe est une classe pour télécharger les images. Celle-ci est également laissée comme exercice. Vous pouvez aussi remplacer les URLs dans le code par le nom de ressources statiques ou encore récupérer la solution depuis le GitHub du projet.
Le framework est prêt, il est temps de passer à la dernière partie: l’extension !
2.2 WatchKit Extension
Cette section va se dérouler en deux grandes étapes:
- La logique associée à la liste des stations
- La logique associée à une station
Configurer la liste des stations
La liste des stations étant le point d’entrée dans notre Watch App, vous allez ici réutiliser le WKInterfaceController principal déjà crée par Xcode: InterfaceController, qui sera renommé en MasterInterfaceController.
Ensuite, déclarez les IBOutlets et effectuez la liaison dans le storyboard.
[java]import WatchKit
import Foundation
import XebiaSkiFramework
class MasterInterfaceController: WKInterfaceController {
@IBOutlet weak var mainTable: WKInterfaceTable![/java]
Par la suite, configurez la WKInterfaceTable de la vue pour afficher les stations de ski provenant du SkiResortDataSource (créée précédemment dans le framework):
[java]// A ajouter dans MasterInterfaceController
private var dataSource = SkiResortDataSource()
override init() {
super.init()
reloadTableData()
}
func reloadTableData() {
mainTable.setNumberOfRows(self.dataSource.count, withRowType: "SkiResortTableRow") // bien vérifier l’identifiant “SkiResortTableRow” dans votre storyboard (cf screenshot suivant)
for var index = 0; index < self.dataSource.count; ++index {
let row = mainTable.rowControllerAtIndex(index) as SkiResortTableRowController
row.configureWithSkiResort(self.dataSource[index])
}
}[/java]
Pour effectuer cette configuration, utilisez une classe custom : SkiResortTableRowController, qui sera utilisée par chacune de nos cellules. Malgré un nom qui peut prêter à confusion, SkiResortTableRowController ne sera pas un WKInterfaceController mais bien un NSObject !
[java]import WatchKit
import XebiaSkiFramework
class SkiResortTableRowController: NSObject {
@IBOutlet weak var titleLabel: WKInterfaceLabel!
func configureWithSkiResort(skiResort: SkiResort) {
self.titleLabel.setText(skiResort.name)
}
}[/java]
Voila vous pouvez (enfin !) lancer le simulateur et voir votre application tourner.
Afficher une station
Le but est de configurer l’application pour afficher les détails d’une application. Pour cela, 3 étapes seront nécessaires :
- Ajouter un interface controller
- Ajouter un segue de type Push
- Configurer le interface controller
Pour la première étape, ajoutez tout simplement un nouveau controller à XebiaSki WatchKit Extension, que vous nommerrez DetailInterfaceController. Configurez votre scène dans storyboard pour lui attribuer une classe custom et définir ses IBOutlet.
[java]import WatchKit
import XebiaSkiFramework
class DetailInterfaceController: WKInterfaceController {
@IBOutlet weak var nameLabel: WKInterfaceLabel!
@IBOutlet weak var temperatureLabel: WKInterfaceLabel!
@IBOutlet weak var photoImageView: WKInterfaceImage!
@IBOutlet weak var dateLabel: WKInterfaceDate![/java]
Deuxième étape, ajoutez un push segue entre SkiResortTableRow et DetailInterfaceController dans le storyboard. Compilez et lancez. Vous devriez voir le template de votre vue apparaître lorsque vous cliquez sur une cellule.
Troisième et dernière étape, configurez le DetailInterfaceController. Pour ce faire il faudra utiliser une fonctionnalité propre à WatchKit : les contextes. Les contextes sont des objets (arbitraires) que l’on peut passer aux WKInterfaceController afin de les configurer.
[java] private var skiResort: SkiResort? // on garde une réf le contexte pour pouvoir le réutiliser ailleurs dans le controller
override awakeWithContext(context: AnyObject!) {
super.awakeWithContext(context)
if let skiResort = context as? SkiResort {
self.skiResort = skiResort
// Une fois le contexte défini, on peut configurer les InterfaceObject de notre vue
self.nameLabel.setText(skiResort.name)
self.temperatureLabel.setText(String(skiResort.temperature) + "°C ")
self.photoImageView = // Ajouter ici le code pour afficher la photo de la station selon que vous téléchargiez l’image ou que vous utilisiez une ressource statique
}
}[/java]
Compilez et lancez. Et voila, vous avez réalisé votre première Watch App !
Conclusion
Ce tutoriel vous a montré comment réaliser une application simple mais complète pour Apple Watch. Le prochain vous montrera comment ajouter des Glances et des notifications pour lancer votre Watch App et la rendre encore plus « badass » aux yeux de vos utilisateurs.
En attendant n’hésitez pas à relire cet article ainsi que celui sur les API WatchKit.
Commentaire
1 réponses pour " WatchKit: Episode II – Codez une application Apple Watch en Swift "
Published by hadrienbbt , Il y a 6 ans
Hi,
I’m a begginer in Swift development, and I see that error in the InterfaceController class:
« fatal error: unexpectedly found nil while unwrapping an Optional value »
It is due to the mainTable Optional variable in the reloadTableData method, but I don’t know how can I fix this…