Por qué la Accesibilidad no es solo una casilla que marcar, sino una superpotencia para tu aplicación
\n\nImagina: creaste una aplicación genial. Interfaz bonita, animaciones ultrarrápidas, código perfecto en Swift. Estás orgulloso de ella. Pero de repente resulta que el 15% de los usuarios no puede usarla. Para ellos, los botones son demasiado pequeños, el texto se fusiona con el fondo y VoiceOver «lee» un revoltijo en lugar del menú. ¿Te suena?
\n\nLa accesibilidad no es una «obligación» ni algo que se hace «para marcar una casilla». Se trata de inclusión, de cuidado y, lo que es importante, de negocio. iOS tiene un framework muy potente que permite adaptar la aplicación a las necesidades de personas con discapacidades visuales, auditivas, motoras y cognitivas. Y Swift nos da todas las herramientas para hacerlo de forma elegante.
\n\nEn este artículo no daremos aburridas conferencias. Analizaremos ejemplos concretos de código que puedes implementar de inmediato en tu proyecto. ¡Allá vamos!
\n\nVoiceOver: cómo «enseñar» a la aplicación a hablar de sí misma
\n\nVoiceOver es un lector de pantalla integrado en iOS. «Narra» todo lo que sucede en la pantalla: texto, botones, gestos. Pero si el desarrollador no prepara la interfaz, VoiceOver puede convertirse en un caos. Vamos a solucionarlo.
\n\nConfiguración básica: accessibilityLabel y accessibilityTraits
\n\nLa forma más sencilla de ayudar a VoiceOver es asignar etiquetas y tipos a los elementos. Por ejemplo, tienes un botón con un icono de corazón. Sin etiqueta, VoiceOver dirá simplemente «botón», pero con etiqueta dirá «Añadir a favoritos».
\n\nlet favoriteButton = UIButton(type: .system)\nfavoriteButton.setImage(UIImage(systemName: "heart"), for: .normal)\nfavoriteButton.accessibilityLabel = "Añadir a favoritos"\nfavoriteButton.accessibilityTraits = .button\n\nObserva accessibilityTraits. Es una pista para VoiceOver sobre cómo interactuar con el elemento. Para un botón — .button, para una imagen — .image, para un título — .header. Usa .selected, .notEnabled y otros para transmitir con precisión el estado.
Agrupación de elementos: cómo evitar que VoiceOver «canse» al usuario
\n\nA veces tiene sentido agrupar varios elementos en un solo bloque semántico. Por ejemplo, una tarjeta de producto: imagen, nombre, precio. Si VoiceOver los lee por separado, el usuario se cansará. La solución es UIAccessibilityElement o shouldGroupAccessibilityChildren.
cardView.shouldGroupAccessibilityChildren = true\ncardView.accessibilityLabel = "Zapatillas Nike Air, 12 990 rublos"\ncardView.accessibilityTraits = .button\n\nAhora VoiceOver leerá toda la tarjeta como un solo elemento. Breve, conciso, claro.
\n\nAcciones personalizadas: cuando se necesita más que un simple «toque»
\n\nHay elementos complejos: deslizadores, interruptores, listas deslizables. Para ellos es importante añadir acciones personalizadas. Por ejemplo, para una celda con las funciones «Eliminar» y «Editar»:
\n\nlet deleteAction = UIAccessibilityCustomAction(\n name: "Eliminar",\n target: self,\n selector: #selector(deleteItem)\n)\nlet editAction = UIAccessibilityCustomAction(\n name: "Editar",\n target: self,\n selector: #selector(editItem)\n)\ncell.accessibilityCustomActions = [deleteAction, editAction]\n\nEl usuario de VoiceOver desliza hacia abajo o hacia arriba para seleccionar una acción. Esto mejora significativamente la experiencia.
\n\nDynamic Type: texto que se adapta a cada persona
\n\nLas personas con visión reducida suelen aumentar el tamaño de fuente en los ajustes de iOS. Si tu aplicación no soporta Dynamic Type, el texto se cortará, se superpondrá o simplemente se volverá ilegible. ¿Cómo evitarlo?
\n\nUsa estilos de fuente dinámicos
\n\nEn lugar de usar un tamaño fijo UIFont.systemFont(ofSize: 16), usa UIFont.preferredFont(forTextStyle: .body).
label.font = UIFont.preferredFont(forText