WWDC 2016 : Bonnes pratiques pour améliorer son application Apple

wwdc16 bonnes pratiquesAvec l’ensemble des changements induits par les nouveautés annoncées lors de la WWDC 2016, une session a été dédiée pour rappeler ou présenter quelques bonnes pratiques faciles à mettre en place pour améliorer ses applications, que ce soit sous iOS, macOS, tvOS ou encore watchOS.

Comment réduire la dette technique

La dette technique existe aussi dans le mobile, car au fur et à mesure des nouvelles versions des OS elle ne cesse de s’alourdir. Pour une application iOS, le premier point à savoir est d’avoir un support à partir de la version N-1. En effet, les études montrent que les personnes sous les OS Apple passent rapidement aux versions supérieures proposées. Finalement, le pourcentage des utilisateurs sous des versions plus anciennes est minime (voir ci-dessous).

déploiement iOS bonnes pratiques

Par exemple, avec iOS, nous sommes aujourd’hui en version 9.3, il suffit donc de cibler la version 8.4 (la dernière version d’iOS 8).

Le deuxième point consiste à réduire les warnings dans un projet. Ce point est particulièrement important, notamment pour les développeurs Swift, car certains avertissements concernent des méthodes dépréciées. Pour éviter de laisser passer les warnings, il est désormais possible avec Swift et Xcode 8 de mettre les warnings en erreurs, ce qui force à les corriger.

Troisième point, qui peut parfois sembler anodin, est le support de l’accessibilité. Heureusement, il est très facile grâce à Xcode et Interface Builder de résoudre cela (voir ci-dessous).

bonne pratique accessibilité

Quatrième et dernier point, qui aide à l’internationalisation d’une application, est l’utilisation des APIs locales. On retrouve par exemple des APIs pour les dimensions, pour le calendrier, les dates, les nombres, etc. Il ne faut donc pas hésiter à s’appuyer dessus, et ne pas chercher à réinventer la roue.

Tirer parti des actions du 3D Touch sur iOS

Avec l’arrivée de l’iPhone 6 et ses nouvelles gestures liées à la pression du doigt, de nouvelles possibilités se sont présentées pour les développeurs. Les utilisateurs possédant un iPhone 6 ou plus récent ont maintenant l’habitude d’utiliser les gestes de Peek, Pop et Quick. Il est donc très agréable pour les utilisateurs lorsqu’une application gère ces gestes.

Utiliser le Catalogue d’Assets

Il est encore fréquent aujourd’hui de voir qu’un projet gère ses images à l’ancienne. Si les développeurs sont encore timides pour changer leurs habitudes, Apple incite pour que ceux-ci passent à l’utilisation du Catalogue d’Assets, un outil qui facilite vraiment la vie des développeurs et intégrateurs.

Le Catalogue d’Assets se base sur la copie des fichiers, ce qui permet de ne pas avoir de référence sur la localisation de base. Dans un projet existant et comportant déjà des images stockées « à l’ancienne », il est possible d’importer ces images dans le catalogue. Celui-ci affichera les images éligibles au mapping, effectué en fonction de la taille des images, vers trois formats : 1x, 2x et 3x.

L’import d’images

Lors de l’import d’images, le catalogue d’Assets va pouvoir intelligemment mapper les trois dimensions grâce au nommage des fichiers (exemple : logo@2x.png, logo@3x.png). Il est important de fournir le plus souvent possible toutes les dimensions demandées, car si une de ces tailles n’est pas présente, l’image sera étirée ou rétrécie selon les dimensions de base. Cette opération se fait au runtime, ce qui impacte directement la qualité finale des images dans une application, ainsi que les performances.

Les assets peuvent être représentés de multiples façons, sur une plateforme ou plus (à chaque plateforme ses dimensions à respecter). Non seulement la plateforme visée peut-être différenciée, mais aussi certaines caractéristiques comme la mémoire ou la version supportée de Metal.

Une application peut évidemment avoir plusieurs catalogues en cas de besoin, pour plus de lisibilité.

Les formats d’image possibles

Pour faciliter le travail, il est possible de travailler avec deux formats d’images. Ces formats sont le PNG, qui fonctionne avec le système de scale expliqué plus haut, et le format PDF. Le format PDF est vectoriel, et une option dans Xcode permet au scale de s’effectuer au buildtime selon le besoin, ce qui simplifie la construction du catalogue d’Assets.

Côté code, c’est le chargement des images qui change. Il est plus concis et utilise maintenant le cache après le premier chargement de l’image.bonne pratique chargement d'image

Astuces boutons arrondis

Nous l’avons vu, la fonction première du catalogue d’Assets est de gérer les images d’une application. Mais ce n’est pas tout : elle possède un éditeur d’Assets, qui s’avère lui aussi très utile.

C’est le cas pour avoir à partir d’une image un bouton arrondis, dont la taille s’adaptera à l’écran. Auparavant, il fallait passer du côté du code, et définir l’arrondi avec la propriété image.stretchableImage.

Maintenant, grâce à l’éditeur d’Assets, il est possible de diviser son image en différentes parties : c’est l’Asset Slicing. En définissant des zones sur l’image en question à ne pas modifier (typiquement, les bords arrondis), et des zones à répéter, l’Asset saura s’adapter selon l’effet voulu.

Être actif dans la communauté

Depuis l’annonce de Swift, devenu Open Source, et une réelle ouverture d’Apple vers la communauté des développeurs, ces derniers sont mis à contribution. Dans ce sens, les équipes d’Apple encouragent fortement les développeurs à soumettre les bugs qu’ils rencontrent en Swift. Une adresse pour cela : BugReport.apple.com. Sans que ce soit réellement une bonne pratique, il est bénéfique pour tous de participer à la communauté.

Rendre son application plus adaptive avec l’injection de dépendance

Si le principe d’injection de dépendance est généralement connu pour les développeurs .NET, il l’est à priori un peu moins pour les développeurs Swift ou Objective-c. C’est pour cela que les équipes d’Apple souhaitent mettre ce pattern en avant. Le but premier de l’injection de dépendance est de rendre une application plus adaptive, notamment pour les vues. L’idée est de rendre les différents ViewControllers indépendants les uns des autres, afin de pouvoir changer facilement l’enchainement selon l’expérience.

Profiter du playground

Pour les développeurs qui travaillent avec Xcode, le playground est devenu un outil très utile. Comme son nom l’indique, il permet d’expérimenter du code façon « bac à sable », et ce de façon très simplifiée et légère.

Il présente malheureusement quelques limites qui demandent encore d’utiliser un projet de test et le simulateur dans certains cas.

Avec l’arrivée proche d’Xcode 8, le playground se voit amélioré. Il va supporter :

  • Le live Playground : un affichage en temps réel d’éléments graphiques
  • Un accès au fichiers ressources de l’application
  • Une gestion des tâches asynchrones (activation d’une variable pour que le playground tourne à l’infini)

Utiliser le cache lors de l’appel à des webservices

Lorsqu’une application utilise des webservices, le cache devient un grand allié du développeur. Le principe est d’avoir de base un fichier en cache qui contient déjà des données. S’il n’y a pas de connexion internet, ce fichier va être utilisé pour avoir des données à afficher. Sinon, la requête au webservice va vérifier si les données ont changé, auquel cas le fichier de cache est mis à jour avec les nouvelles données. Cela évite des appels répétitifs parfois lourd si beaucoup de données transitent.

Cette bonne pratique est un basique dans le développement mobile, mais il est intéressant de la rappeler.

Respecter les guidelines UI sur chaque plateforme

La multiplicité des plateformes proposées par Apple (iOS, macOS, tvOS, watchOS), et l’hyper connectivité entre celles-ci offre d’autant plus d’opportunités aux développeurs d’applications. Mais il ne suffit pas de cibler toutes les plateformes pour faire de son application un succès. A chaque plateforme correspond son expérience propre. Si Apple pousse les créateurs d’application à être présents sur toutes leurs plateformes, il est conseillé de respecter leurs différentes guidelines.

Une des principales astuce consiste à utiliser les directives de code pour adapter celui-ci en fonction de l’interface sur laquelle il tournera. Mais il faut tout de même se rapporter aux documents de guidelines. Il existe d’ailleurs sur le site d’Apple des guides rapides pour chaque plateforme :

Le mot de la fin

Nous avons vu dans cet article un ensemble de bonnes pratiques mises en avant par les équipes d’Apple à la WWDC 2016. Tous ces conseils ont pour but de favoriser l’adoption des applications par les utilisateurs, ou d’améliorer leur pérennité. Que ce soit côté développement ou design, les bonnes pratiques présentées sont aisément applicables.

Alors n’attendez plus pour créer ou améliorer vos applications !

WWDC 2016 : Quoi de neuf pour les CollectionView ?

WWDC 2016 CollectionViewComme chaque année, au mois de juin, se déroule la grande conférence d’Apple qui cible principalement les annonces pour les développeurs, la WWDC.

La keynote a montré nombre de nouveautés, notamment iOS 10, le changement de nom d’OS X vers Mac OS et sa nouvelle version, etc. Si iOS 10 apporte peu de changements côté design, du côté des développeurs cela va changer beaucoup de choses : nouvelle version de Swift, nouvelles APIs (Siri, Messages, etc.), autant de points qui offrent de nouvelles possibilités de jeux et d’applications sur iOS.

Si les conférences techniques de la WWDC s’axent sur le langage Swift, elles sont également intéressantes pour un développeur Xamarin, car certaines présentent des APIs ou nouveautés graphiques qui seront également disponible pour Xamarin.iOS peu après la sortie officile d’iOS 10.

La question de la CollectionView est un sujet récurrent lors du développement d’applications iOS, et une présentation lui a été dédiée pour montrer les améliorations et nouveautés dont elle va bénéficier.

Le scroll et ses performances

La première problématique abordée est celle du scroll dans une CollectionView. En effet, si globalement les performances sont plus que correctes, ce n’était pas assez pour les développeurs chez Apple.

Pour rappel, voici comment se décompose le cycle de vie d’une cellule d’une collection ou d’une table sous iOS 9 et versions antérieures :

  1. Lors d’un scroll, et qu’une nouvelle cellule est requise à l’affichage, cette cellule est sortie de la queue de réutilisation (« reuse queue »), et l’appel à la méthode PrepareForReuse permet de réinitialiser le template de la cellule à son état initial, pour qu’elle puisse recevoir de la nouvelle donnée
  2. La méthode CellForItemAtIndexPath est appelée. C’est ici que la cellule sera peuplée avec de la donnée ou configurée en fonction du besoin
  3. Juste avant que la cellule apparaisse à l’écran, la méthode WillDisplayCell est appelée, et c’est dans celle-ci que doivent être fait les derniers traitements avant l’affichage
  4. Enfin, lorsque la cellule disparait de la zone visible par l’utilisateur, la méthode DidEndDisplayingCell est appelée

Le renouveau du cycle de vie

Avec iOS 10, les étapes sont identiques, mais le timing d’appel aux méthodes citées précédemment diffère :

  1. Quand on scroll, la cellule dans la reuse queue est récupérée bien avant qu’elle n’ait besoin d’être affichée, et s’en suit l’appel à la méthode PrepareForReuse
  2. Pas de changement du côté de l’appel à la méthode CellForItemAtIndexPath
  3. Petite différence de timing sur la méthode WillDisplayCell, puisque celle-ci est appelée pile au moment où la cellule commence à apparaitre
  4. DidEndDisplayingCell est appelée lorsque la cellule va disparaître de l’écran. Ici la différence avec les versions antérieures d’iOS est que jusqu’à présent, à ce stade la cellule retourne dans la reuse queue, et si elle a besoin d’être réaffichée, il faut repasser par tout le process (CellForItem, WillDisplayCell). Avec iOS 10, seule la méthode WillDisplayCell sera rappelée.

La différence entre les enchainements ne sont pas flagrants lorsqu’ils sont décris tels quels, mais en démonstration on remarque une différence de fluidité lors d’un scroll rapide et relativement long.

CollectionView iOS Cell LifecycleDans le cas d’une CollectionView avec plusieurs colonnes, iOS 10 va s’occuper pour chaque ligne de charger une cellule à la fois pour le PrepareForReuse et CellForItemAtIndexPath (voir image ci-dessus). En revanche la méthode WillDisplayCell est appelée en même temps pour chaque colonne de la ligne. Cela améliore également les performances lors d’un scroll plutôt rapide et permet un visuel plus fluide.

A noter que les changements apportés avec iOS 10 n’impactent pas le développement, puisque c’est uniquement côté API que le timing est géré.

Le Cell Pre-Fetching, autre nouveauté pour iOS 10

Cette fonctionnalité, activée par défaut sous iOS 10, permettra comme son nom l’indique de pré-charger, et ce en asynchrone, les données des cellules. Combinée au système de réutilisation de cellule amélioré pour cette nouvelle version, les performances lors du scroll n’en seront que plus bonnes, ce qui est une excellente nouvelle pour les développeurs.

Le Pre-Fetching sera disponible pour les CollectionView, mais aussi pour les TableView, et une ligne suffit pour la désactiver.

Afin de profiter au maximum des performances qu’offrent le Pre-Fetching, un ensemble de bonnes pratique seront à appliquer :

  • Il faudra centraliser tout le « contenu lourd » (création, remplissage de données, etc.) dans la méthode CellFormItemAtIndexPath. Il est en revanche important de savoir que cette méthoe peut préparer une cellule qui ne sera jamais affichée
  • A contrario, les méthodes WillDisplay et DidEndDisplay devront traiter peu de choses

Le cas des modèles couteux

Il est très fréquent lors du développement d’une application d’avoir des étapes couteuses en terme de performances, tels quel l’accès aux images, parsing ou décodage d’images ou encore l’accès à la DB. Pour ces cas-là, Apple propose une nouvelle API pour les collections et tables, qui complète le Delegate et le DataSource : le PreFetchingDataSource.

Ce protocole (sous Swift) possède deux méthodes : une qui va s’occuper de récupérer en asynchrone les données, une autre pour annuler en cas de basse priorité. L’astuce pour bien gérer ces deux méthodes dans l’exemple d’un scroll dans un sens puis dans l’autre : il faut utiliser la méthode cancelPreFecthingForItemsAt pour annuler le chargement des éléments qui ne seront pas affichés.

CollectionView prefetchingAPI

Grâce au Cell Pre-Fetching, associé au nouveau fonctionnement du cycle de vie d’une cellule sous iOS 10, le scroll dans une Collection ou une Table sera encore plus fluide qu’il ne l’est à présent.

L’auto resize des cellules améliorée pour iOS 10 (CollectionView)

L’API de taille auto-adaptable (« self-sizing ») pour une cellule est disponible depuis iOS 8 pour les TableView et CollectionView, et permet à une cellule d’adapter elle-même sa taille en fonction de son contenu. En donnant au départ une taille estimée, il est possible grâce à différentes méthodes comme par exemple AutoLayout de modifier au runtime cette taille selon le contenu de chaque cellule. Cette feature, très intéressante, rencontre tout de même un problème quand le développeur doit estimer la taille de la cellule.

Cette API va donc elle aussi voir son fonctionnement amélioré. Il sera possible sous iOS 10 d’avoir une estimation automatique de la taille de la cellule, grâce à cette propriété : layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize. Elle permet de déléguer le calcul de la taille de la cellule à la CollectionView, au lieu du développeur. Finalement, la taille estimée des cellules se fera en fonction de la taille réelle des cellules déjà générées. Elle pourra donc changer au fur et à mesure pour atteindre une taille la plus proche possible de ce qui est attendu visuellement.

Ce fonctionnement permet d’être plus précis par rapport au comportement attendu, mais offre aussi de meilleures performances lors de la construction de la collection.

La réorganisation de cellules interactive

Disponible depuis iOS 9, cette API permet de réordonner des éléments d’une CollectionView grâce au Drag&Drop, avec dans le cas des cellules à taille différente une adaptivité de la taille lors de la réorganisation.

Petit rappel sur cette fonctionnalité :CollectionView InteractiveReordering

  • Quatre méthodes permettent son utilisation et sa gestion
  • Dans le UICollectionViewController, il faut activer une variable: installStandardGestureForInteractiveMovement

La nouveauté sous iOS 10 sera le support du paging pour le déplacement dans une CollectionView. Cela apportera la même expérience utilisateur que sur la page Home de l’iPhone, lorsque des applications sont déplacées.

Le refresh control

En bonus, le UIRefreshControl sera maintenant directement supporté dans les CollectionView, TableView et ScrollView.

CollectionView RefreshControl

Conclusion

Nous avons pu voir au travers de cet article que les développeurs chez Apple sont très attachés à l’expérience utilisateur et cherchent à améliorer toujours plus les performances de leurs contrôles. L’exemple des nouveautés qui affecteront la CollectionView (mais aussi la TableView dans certains cas) promettent d’être très intéressantes, d’autant plus qu’elles ne présentent à priori pas de grandes modifications côté code. On dit souvent que les développeurs sont feignants, c’est donc ici une excellente nouvelle 🙂

image-463

Vivement la sortie d’iOS 10, et la disponibilité de ces APIs avec Xamarin !