Vincent Tourraine
Blog

iOS 13 : s’adapter au mode sombre

#dev #iOS

Le mode sombre ne laisse pas indifférent. Mais que vous soyez enthousiasmé ou consterné, Apple annonce « Dark Mode » comme la nouveauté principale d’iOS 13. Si vous développez une application iPhone ou iPad, ça signifie qu’il vous faudra supporter cette fonctionnalité aussi tôt que possible, pour ne pas recevoir une pluie d’avis négatifs sur l’App Store déplorant son absence.

Mode sombre sur iOS 13
Mode sombre sur iOS 13

La bonne nouvelle, c’est que le mode sombre peut être très facile à prendre en charge. La mauvaise, c’est que ça peut aussi s’avérer très complexe, selon votre façon de configurer l’interface de votre application.

Configuration par défaut

Premier conseil : utilisez autant que possible les composants standards dans leur configuration par défaut.

Par exemple, si vous voulez afficher un texte en noir sur fond blanc, c’est justement la configuration par défaut d’un UILabel dans une UIView. Ne modifiez les textColor, backgroundColor, etc, que si c’est absolument nécessaire.

Ça peut sembler évident, mais c’est le genre de code qui s’accumule facilement, surtout pour des projets plus anciens. Moins de code == moins de problèmes.

Couleurs dynamiques

On arrive au plus important : les couleurs. Le SDK iOS 13 prend en charge les couleurs « dynamiques ». Ce sont des UIColor pouvant prendre plusieurs valeurs, typiquement une pour le mode clair et une pour le mode sombre. En utilisant des couleurs dynamiques, la prise en charge du mode sombre est automatique. Pas la moindre ligne de code à ajouter.

Pour utiliser ces couleurs dynamiques, vous avez plusieurs options :

Sélection des couleurs avec Xcode 11
Sélection des couleurs avec Xcode 11

Ces nouvelles couleurs sont uniquement disponibles sur iOS 13. Si votre application supporte des versions antérieures, il faudra adapter votre projet, avec là aussi plusieurs options :

@implementation UIColor (XYZ)

+(UIColor *)xyz_labelColor {
  if (@available(iOS 13.0, *)) {
    return [UIColor labelColor];
  } else {
    return [UIColor blackColor];
  }
}

@end

Une dernière note concernant les couleurs : les CGColor ne sont pas dynamiques. On les utilise parfois, par exemple pour ajouter une bordure ou une ombre à une vue, en passant par le CALayer. Les éléments utilisant des CGColor, même créées à partir d’UIColor, ne s’adapteront pas automatiquement au mode sombre. Il vous faudra alors explicitement les mettre à jour avec des CGColor différentes. Je vous explique comment en bas de cet article, dans la section « Implémentation personnalisée ».

Images

Vous pouvez utiliser des images spécifiques au mode sombre. Là aussi, UIImageView s’occupe de tout, et s’adapte automatiquement en fonction du mode actif, si l’image dispose d’une variante sombre. Avec un Asset Catalog, il suffit de spécifier la variante pour chaque image concernée, comme pour les couleurs nommées.

Glyphes

On peut aussi évoquer les glyphes, c’est à dire les images avec un rendu en mode « template », qui sont colorisées selon le tintColor de la vue concernée. Concrètement, c’est ce qu’on utilise pour les icônes de boutons : le « + » pour l’ajout, le carré avec une flèche vers le haut pour le partage, etc. iOS 13 ajoute par ailleurs les « SF Symbols », une collection de quelques centaines de glyphes disponibles avec variantes de taille et d’épaisseur.

Dans tous les cas, il suffit d’utiliser une couleur dynamique en tintColor pour que le rendu de l’image s’adapte automatiquement au mode actif.

Implémentation personnalisée

La prise en charge du mode sombre est largement automatisée, mais il est également possible d’intervenir manuellement.

traitCollectionDidChange: est la méthode la plus importante, puisque c’est UITraitCollection qui contient la valeur du mode, clair ou sombre, avec la propriété userInterfaceStyle. Vous pouvez surcharger cette méthode à différents niveaux, sur UIView, UIViewController, UIScreen et UIPresentationController. Documentation

-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
  [super traitCollectionDidChange:previousTraitCollection];

  if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
    // ...
  }
}

Désactiver le mode sombre

Toute application compilée avec le SDK iOS 13 supporte a priori le mode sombre.

Si vous souhaitez modifier la prise en charge automatique pour une partie de votre application, vous pouvez assigner la propriété overrideUserInterfaceStyle sur une UIView ou un UIViewController pour forcer un mode spécifique.

Enfin, si vous souhaitez désactiver complètement le mode sombre, vous pouvez ajouter la clé UIUserInterfaceStyle dans le fichier Info.plist de votre application, avec une valeur de Light.