Pourquoi l'accessibilité n'est pas qu'une simple case à cocher, mais un super-pouvoir pour votre application
\n\nImaginez : vous avez créé une application géniale. Une interface magnifique, des animations fulgurantes, un code Swift parfait. Vous en êtes fier. Mais soudain, il s'avère que 15 % des utilisateurs ne peuvent pas l'utiliser. Pour eux, les boutons sont trop petits, le texte se confond avec le fond, et VoiceOver « lit » du charabia au lieu du menu. Cela vous semble familier ?
\n\nL'accessibilité (Accessibility) n'est pas une « obligation » ni un « à faire pour la forme ». C'est une question d'inclusivité, de bienveillance et, ce qui n'est pas négligeable, d'affaires. iOS dispose d'un framework extrêmement puissant qui permet d'adapter l'application aux besoins des personnes ayant des déficiences visuelles, auditives, motrices et cognitives. Et Swift nous donne tous les outils pour le faire avec élégance.
\n\nDans cet article, nous n'allons pas faire de cours ennuyeux. Nous allons analyser des exemples de code concrets que vous pouvez immédiatement intégrer à votre projet. C'est parti !
\n\nVoiceOver : comment « apprendre » à votre application à parler d'elle-même
\n\nVoiceOver est le lecteur d'écran intégré à iOS. Il « vocalise » tout ce qui se passe à l'écran : texte, boutons, gestes. Mais si le développeur n'a pas préparé l'interface, VoiceOver peut devenir un chaos. Corrigeons cela.
\n\nConfiguration de base : accessibilityLabel et accessibilityTraits
\n\nLa façon la plus simple d'aider VoiceOver est de définir des étiquettes et des types d'éléments. Par exemple, vous avez un bouton avec une icône de cœur. Sans étiquette, VoiceOver dira simplement « bouton », mais avec une étiquette, il dira « Ajouter aux favoris ».
\n\nlet favoriteButton = UIButton(type: .system)\nfavoriteButton.setImage(UIImage(systemName: "heart"), for: .normal)\nfavoriteButton.accessibilityLabel = "Ajouter aux favoris"\nfavoriteButton.accessibilityTraits = .button\n\nNotez l'utilisation de accessibilityTraits. C'est une indication pour VoiceOver sur la façon d'interagir avec l'élément. Pour un bouton — .button, pour une image — .image, pour un titre — .header. Utilisez .selected, .notEnabled et d'autres pour transmettre précisément l'état.
Regroupement d'éléments : comment éviter que VoiceOver « noie » l'utilisateur
\n\nIl est parfois logique de regrouper plusieurs éléments en un seul bloc sémantique. Par exemple, une fiche produit : image, nom, prix. Si VoiceOver les lit séparément, l'utilisateur se fatiguera. La solution est UIAccessibilityElement ou shouldGroupAccessibilityChildren.
cardView.shouldGroupAccessibilityChildren = true\ncardView.accessibilityLabel = "Baskets Nike Air, 12 990 roubles"\ncardView.accessibilityTraits = .button\n\nDésormais, VoiceOver lira toute la fiche comme un seul élément. Court, concis, clair.
\n\nActions personnalisées : quand il faut plus qu'un simple « tap »
\n\nIl existe des éléments complexes : curseurs, interrupteurs, listes à balayer. Pour eux, il est important d'ajouter des actions personnalisées. Par exemple, pour une cellule avec les fonctions « Supprimer » et « Modifier » :
\n\nlet deleteAction = UIAccessibilityCustomAction(\n name: "Supprimer",\n target: self,\n selector: #selector(deleteItem)\n)\nlet editAction = UIAccessibilityCustomAction(\n name: "Modifier",\n target: self,\n selector: #selector(editItem)\n)\ncell.accessibilityCustomActions = [deleteAction, editAction]\n\nL'utilisateur de VoiceOver balaye vers le bas ou vers le haut pour choisir une action. Cela améliore considérablement l'expérience.
\n\nDynamic Type : un texte qui s'adapte à chacun
\n\nLes personnes malvoyantes augmentent souvent la taille de la police dans les réglages iOS. Si votre application ne prend pas en charge Dynamic Type, le texte sera tronqué, se superposera ou deviendra tout simplement illisible. Comment éviter cela ?
\n\nUtilisation des styles de police dynamiques
\n\nAu lieu d'utiliser un UIFont.systemFont(ofSize: 16) rigide, utilisez UIFont.preferredFont(forTextStyle: .body).
label.font = UIFont.preferredFont(forText