Interfaces de usuario de iOS: guiones gráficos frente a NIB frente a código personalizado

Publicado: 2022-03-11

A menudo escucho a los desarrolladores de iOS hacer alguna variante de la misma pregunta clave:

¿Cuál es la mejor manera de desarrollar una interfaz de usuario en iOS: a través de guiones gráficos, NIB o código?

Las respuestas a esta pregunta, explícita o implícitamente, tienden a suponer que se debe hacer una elección mutuamente excluyente, una que a menudo se aborda por adelantado, antes del desarrollo.

Soy de la opinión de que la respuesta debería tomar la forma de una o más contrapreguntas .

¿Cuál es el “mejor” coche?

Me explico con un ejemplo fuera de tema. Digamos que quiero comprar un auto y te hago una simple pregunta: "¿Cuál es la mejor opción?"

¿Puede realmente responder sugiriendo un modelo o incluso una marca? No es probable, a menos que sugiera un Ferrari. En su lugar, probablemente responda con algunas otras preguntas, como:

  • ¿Cuál es tu presupuesto?
  • ¿Cuántos asientos necesitas?
  • ¿Te importa el consumo de combustible?
  • ¿Cómo te sientes acerca de los autos deportivos?

Es obvio que no existe un automóvil bueno o malo a menos que se coloque en un contexto adecuado: solo hay un automóvil bueno o malo según las necesidades específicas.

Volver al diseño de la interfaz de usuario de iOS

Al igual que con nuestra consulta sobre automóviles, la pregunta "¿Cuál es la mejor manera de desarrollar una interfaz de usuario de iOS?" carece de contexto. Y sorprendentemente, la respuesta no tiene por qué ser un caso general.

En términos generales, hay tres tipos de enfoques de diseño de interfaz de usuario que puede tomar, cada uno con sus pros y sus contras, sus fanáticos y sus enemigos:

  • Guiones gráficos de iOS : una herramienta visual para diseñar múltiples vistas de aplicaciones y las transiciones entre ellas.
  • NIB (o XIB) : cada archivo NIB corresponde a un único elemento de vista y se puede diseñar en Interface Builder, lo que lo convierte también en una herramienta visual. Tenga en cuenta que el nombre "NIB" se deriva de la extensión del archivo (anteriormente .nib y ahora .xib, aunque la antigua pronunciación ha persistido).
  • Código personalizado : es decir, no hay herramientas de GUI, sino que maneja todo el posicionamiento personalizado, la animación, etc. mediante programación.

Ninguna de estas opciones es universalmente mejor que cualquier otra (a pesar de lo que pueda escuchar).

Los guiones gráficos, por ejemplo, son la última incorporación al conjunto de herramientas de la interfaz de usuario de iOS. Me han dicho que son el futuro, que reemplazarán las NIB y las UI de código personalizado. Veo Storyboards como una herramienta útil, pero no tanto un reemplazo como un complemento para NIB y código personalizado. Los guiones gráficos son la elección correcta en algunas situaciones, pero no en todas.

Este tutorial de desarrollo de iOS busca explorar la diferencia entre 3 enfoques para el diseño de la interfaz de usuario de iOS.

Además, ¿por qué debería apegarse estáticamente a una sola opción cuando puede usarlas todas (en el mismo proyecto), eligiendo el mecanismo que mejor se adapte al problema específico en cuestión?

Esta es una pregunta que, en mi opinión, puede generalizarse a un nivel superior, y cuya respuesta ocupa un lugar destacado en mi lista de principios de desarrollo de software: No existe un lenguaje, marco o tecnología universal que sea la mejor opción universal para todos. problema de desarrollo de software. Lo mismo es cierto para el diseño de la interfaz de usuario de iOS.

En este tutorial de desarrollo de iOS, exploraremos cada uno de estos métodos e introduciremos casos de uso en los que deberían y no deberían emplearse, así como las formas en que pueden combinarse.

Guiones gráficos de iOS

El error clásico de un principiante es crear un guión gráfico de iOS masivo para todo el proyecto. Yo también cometí este error cuando comencé a trabajar con guiones gráficos (probablemente porque es una ruta tentadora).

El error clásico de un principiante es crear un guión gráfico masivo para todo el proyecto. Un Storyboard es un tablero con una historia que contar. No debe usarse para mezclar historias no relacionadas en un gran volumen.

Como su nombre lo indica, un Storyboard es un tablero con una historia que contar . No debe usarse para mezclar historias no relacionadas en un gran volumen. Un guión gráfico debe contener controladores de vista que estén lógicamente relacionados entre sí, lo que no significa que todos los controladores de vista.

Por ejemplo, tiene sentido usar guiones gráficos al manejar:

  • Un conjunto de vistas para autenticación y registro.
  • Un flujo de entrada de pedidos de varios pasos.
  • Un flujo similar a un asistente (es decir, un tutorial).
  • Un conjunto maestro-detalle de vistas (por ejemplo, listas de perfiles, detalles de perfil).

Mientras tanto, se deben evitar los guiones gráficos grandes, incluidos los guiones gráficos únicos de toda la aplicación (a menos que la aplicación sea relativamente simple). Antes de profundizar más, veamos por qué.

La locura de los grandes guiones gráficos de iOS

Los guiones gráficos grandes, además de ser difíciles de explorar y mantener, agregan una capa de complejidad al entorno de un equipo: cuando varios desarrolladores trabajan en el mismo archivo de guión gráfico al mismo tiempo, los conflictos de control de fuente son inevitables . Y aunque un guión gráfico se representa internamente como un archivo de texto (un archivo XML, en realidad), la fusión no suele ser trivial.

Cuando los desarrolladores ven el código fuente, le atribuyen un significado semántico. Entonces, cuando se fusionan manualmente, pueden leer y comprender ambos lados de un conflicto y actuar en consecuencia. Un guión gráfico, en cambio, es un archivo XML administrado por Xcode, y el significado de cada línea de código no siempre es fácil de entender.

Tomemos un ejemplo muy simple: digamos que dos desarrolladores diferentes cambian la posición de una UILabel (usando el diseño automático), y el último empuja su cambio, produciendo un conflicto como este (observe los atributos de id en conflicto):

 <layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides> <layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides>

La id en sí misma no proporciona ninguna indicación sobre su verdadero significado, por lo que no tiene nada con lo que trabajar. La única solución significativa es elegir uno de los dos lados del conflicto y descartar el otro. ¿Habrá efectos secundarios? ¿Quién sabe? No tú.

Para aliviar estos problemas de diseño de la interfaz de iOS, el enfoque recomendado es utilizar varios guiones gráficos en el mismo proyecto.

Cuándo usar guiones gráficos

Los guiones gráficos se utilizan mejor con varios controladores de vista interconectados, ya que su principal simplificación es la transición entre los controladores de vista. Hasta cierto punto, se pueden considerar como una composición de NIB con flujos visuales y funcionales entre controladores de vista.

Los guiones gráficos se utilizan mejor con varios controladores de vista interconectados, ya que su principal simplificación es la transición entre los controladores de vista.

Además de facilitar el flujo de navegación, otra ventaja distintiva es que eliminan el código repetitivo necesario para mostrar, empujar, presentar y descartar controladores de vista. Además, los controladores de vista se asignan automáticamente, por lo que no es necesario alloc e iniciar init .

Por último, aunque los guiones gráficos se utilizan mejor para escenarios que involucran múltiples controladores de vista, también es defendible usar un guión gráfico cuando se trabaja con un solo controlador de vista de tabla por tres razones:

  • La capacidad de diseñar prototipos de celdas de tabla en el lugar ayuda a mantener las piezas juntas.
  • Se pueden diseñar varias plantillas de celdas dentro del controlador de vista de la tabla principal.
  • Es posible crear vistas de tablas estáticas (una adición largamente esperada que lamentablemente solo está disponible en Storyboards).

Se podría argumentar que también se pueden diseñar múltiples plantillas de celda utilizando NIB. En verdad, esto es solo una cuestión de preferencia: algunos desarrolladores prefieren tener todo en un solo lugar, mientras que a otros no les importa.

Cuándo no usar guiones gráficos de iOS

Algunos casos:

  • La vista tiene un diseño complicado o dinámico, que se implementa mejor con código.
  • La vista ya está implementada con NIB o código.

En esos casos, podemos dejar la vista fuera del guión gráfico o incrustarla en un controlador de vista. El primero rompe el flujo visual del Storyboard, pero no tiene implicaciones funcionales o de desarrollo negativas. Este último conserva este flujo visual, pero requiere esfuerzos de desarrollo adicionales ya que la vista no está integrada en el controlador de vista: simplemente está incrustado como un componente, por lo tanto, el controlador de vista debe interactuar con la vista en lugar de implementarla.

Pros y contras generales

Ahora que tenemos una idea de cuándo los guiones gráficos son útiles en el diseño de la interfaz de usuario de iOS, y antes de pasar a los NIB en este tutorial, repasemos sus ventajas y desventajas generales.

Ventaja: Rendimiento

Intuitivamente, puede asumir que cuando se carga un Storyboard, todos sus controladores de vista se instancian inmediatamente. Afortunadamente, esto es solo una abstracción y no se aplica a la implementación real: en su lugar, solo se crea el controlador de vista inicial, si lo hay. Los otros controladores de vista se instancian dinámicamente, ya sea cuando se realiza una transición o manualmente desde el código.

Ventaja: Prototipos

Los guiones gráficos simplifican la creación de prototipos y la maquetación de las interfaces de usuario y el flujo. En realidad, se puede implementar fácilmente una aplicación prototipo de trabajo completo con vistas y navegación utilizando guiones gráficos y solo unas pocas líneas de código.

Con: reutilización

Cuando se trata de mover o copiar, los guiones gráficos de iOS están mal posicionados. Un Storyboard debe moverse junto con todos sus controladores de vista dependientes. En otras palabras, un único controlador de vista no se puede extraer y reutilizar individualmente en otro lugar como una única entidad independiente; depende del resto del guión gráfico para funcionar.

Con: flujo de datos

A menudo, los datos deben pasarse entre los controladores de vista cuando una aplicación realiza la transición. Sin embargo, el flujo visual del Storyboard se rompe en este caso ya que no hay rastro de que esto suceda en el Interface Builder. Los guiones gráficos se encargan de manejar el flujo entre los controladores de vista, pero no el flujo de datos. Por lo tanto, el controlador de destino debe configurarse con código, anulando la experiencia visual.

Los guiones gráficos se encargan de manejar el flujo entre los controladores de vista, pero no el flujo de datos.

En tales casos, tenemos que confiar en un prepareForSegue:sender , con un esqueleto if/else-if como este:

 - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { NSString *identifier = [segue identifier]; if ([identifier isEqualToString@"segue_name_1"]) { MyViewController *vc = (MyViewController *) [segue destinationViewController]; [vc setData:myData]; } else if ([identifier isEqualToString@"segue_name_2"]) { ... } else if ... }

Considero que este enfoque es propenso a errores e innecesariamente detallado.

NIB

Los NIB son la forma más antigua (más) de realizar el diseño de la interfaz de iOS.

En este caso, "antiguo" no significa "malo", "obsoleto" o "obsoleto". De hecho, es importante comprender que los Storyboards de iOS no son un reemplazo universal para los NIB; simplemente simplifican la implementación de la interfaz de usuario en algunos casos.

Con NIB, se puede diseñar cualquier vista arbitraria, que luego el desarrollador puede adjuntar a un controlador de vista según sea necesario.

Si aplicamos el diseño orientado a objetos a nuestras interfaces de usuario, tiene sentido dividir la vista de un controlador de vista en módulos separados , cada uno implementado como una vista con su propio archivo NIB (o con varios módulos agrupados en el mismo archivo). La clara ventaja de este enfoque es que cada componente es más fácil de desarrollar, más fácil de probar y más fácil de depurar.

Los NIB comparten los problemas de conflicto de combinación que vimos con Storyboards, pero en menor medida, ya que los archivos NIB funcionan a menor escala.

Cuándo usar NIB para el diseño de interfaz de usuario de iOS

Un subconjunto de todos los casos de uso sería:

  • Vistas modales
  • Vistas sencillas de inicio de sesión y registro
  • Ajustes
  • Ventanas emergentes
  • Plantillas de vista reutilizables
  • Plantillas de celdas de tabla reutilizables

Mientras tanto…

Cuándo no usar NIB

Debe evitar el uso de NIB para:

  • Vistas con contenido dinámico, donde el diseño cambia significativamente según el contenido.
  • Vistas que, por naturaleza, no se pueden diseñar fácilmente en Interface Builder.
  • Ver controladores con transiciones complicadas que podrían simplificarse con Guiones gráficos.

Pros y contras generales

De manera más general, analicemos los pros y los contras del uso de NIB.

Ventaja: reutilización

Los NIB son útiles cuando se comparte el mismo diseño en varias clases.

Como un caso de uso simple, se podría implementar una plantilla de vista que contenga un nombre de usuario y un campo de texto de contraseña con las vistas hipotéticas TTLoginView y TTSignupView , las cuales podrían originarse en el mismo NIB. TTLoginView tendría que ocultar el campo de contraseña, y ambos tendrían que especificar las etiquetas estáticas correspondientes (como 'Ingrese su nombre de usuario' frente a 'Ingrese su contraseña'), pero las etiquetas tendrían la misma funcionalidad básica y diseños similares.

Ventajas y desventajas: rendimiento

Los NIB se cargan de forma perezosa, por lo que no utilizan la memoria hasta que es necesario. Si bien esto puede ser una ventaja, hay latencia en el proceso de carga diferida, lo que también lo convierte en una desventaja.

Código personalizado de iOS (IU programáticas)

Cualquier diseño de interfaz de iOS que se pueda hacer con guiones gráficos y NIB también se puede implementar con código sin procesar (hubo un tiempo, por supuesto, en que los desarrolladores no podían darse el lujo de contar con un conjunto de herramientas tan completo).

Lo que no se puede hacer con NIB y Storyboards siempre se puede implementar con código.

Quizás lo que es más importante, lo que no se puede hacer con NIB y Storyboards siempre se puede implementar con código, siempre que, por supuesto, sea técnicamente factible. Otra forma de verlo es que los NIB y los guiones gráficos se implementan con código, por lo que su funcionalidad será, naturalmente, un subconjunto. Pasemos directamente a los pros y los contras.

Pro: bajo el capó

La mayor ventaja de crear una interfaz de usuario de iOS mediante programación: si sabe cómo codificar una interfaz de usuario, entonces sabe lo que sucede debajo del capó , mientras que lo mismo no es necesariamente cierto para NIB y Storyboards.

Para hacer una comparación: una calculadora es una herramienta útil. Pero no es malo saber cómo realizar cálculos manualmente.

Esto no se limita a iOS, sino a cualquier herramienta RAD visual (p. ej., Visual Studio y Delphi, solo por nombrar algunas). Los entornos RAD de HTML visual representan un caso límite típico: se utilizan para generar código (a menudo mal escrito), afirmando que no se necesitan conocimientos de HTML y que todo se puede hacer visualmente. Pero ningún desarrollador web implementaría una página web sin ensuciarse las manos: saben que el manejo manual de HTML y CSS sin procesar conducirá a un código más modular y más eficiente.

Por lo tanto, dominar la codificación de las interfaces de usuario de iOS le brinda más control y una mayor conciencia de cómo encajan estas piezas, lo que eleva su límite superior como desarrollador.

Pro: cuando el código es la única opción

También hay casos en los que el código iOS personalizado es la única opción para el diseño de la interfaz de usuario. Los diseños dinámicos, donde los elementos de la vista se mueven y el flujo o el diseño se ajusta significativamente según el contenido, son ejemplos típicos.

Pro: Conflictos de fusión

Si bien los NIB y los guiones gráficos sufrieron significativamente los conflictos de fusión, el código no tiene la misma falla. Todo el código tiene un significado semántico, por lo que resolver conflictos no es más difícil de lo habitual.

Con: creación de prototipos

Es difícil saber cómo se verá un diseño hasta que lo veas en acción. Además, no puede colocar visualmente las vistas y los controles, por lo que traducir las especificaciones de diseño en una vista tangible puede llevar mucho más tiempo, en comparación con NIB y Storyboards, que le brindan una vista previa inmediata de cómo se representarán las cosas.

Con: refactorización

La refactorización de código que fue escrito hace mucho tiempo o por otra persona también se vuelve mucho más complicada: cuando los elementos se posicionan y animan con métodos personalizados y números mágicos, las sesiones de depuración pueden volverse arduas.

Ventaja: Rendimiento

En términos de rendimiento, Storyboards y NIB están sujetos a la sobrecarga de carga y análisis; y al final, se traducen indirectamente en código. No hace falta decir que esto no sucede con las IU creadas con código.

Ventaja: reutilización

Cualquier vista implementada mediante programación se puede diseñar de forma reutilizable. Veamos algunos casos de uso:

  • Dos o más vistas comparten un comportamiento común, pero son ligeramente diferentes. Una clase base y dos subclases resuelven el problema con elegancia.
  • Un proyecto tiene que bifurcarse, con el objetivo de crear una única base de código, pero generando dos (o más) aplicaciones diferentes, cada una con personalizaciones específicas.

El mismo proceso de diseño de interfaz de usuario sería mucho más complicado con NIB y Storyboards. Los archivos de plantilla no permiten la herencia y las posibles soluciones se limitan a lo siguiente:

  • Duplique los archivos NIB y Storyboard. Después de eso, tienen vidas separadas y ninguna relación con el archivo original.
  • Anule la apariencia y el comportamiento con código, lo que puede funcionar en casos simples, pero puede generar complicaciones significativas en otros. Las anulaciones pesadas con código también pueden hacer que el diseño visual sea inútil y convertirse en una fuente constante de dolores de cabeza, por ejemplo, cuando cierto control se muestra de una manera en Interface Builder, pero se ve completamente diferente cuando la aplicación se está ejecutando.

Cuándo usar el código

A menudo es una buena decisión usar código personalizado para el diseño de la interfaz de usuario de iOS cuando tiene:

  • Diseños dinámicos.
  • Vistas con efectos, como esquinas redondeadas, sombras, etc.
  • Cualquier caso en el que el uso de NIBs y Storyboards sea complicado o inviable.

Cuándo no usar el código

En general, siempre se pueden usar interfaces de usuario creadas con código. Rara vez son una mala idea, así que pondría un aquí.

Aunque los NIB y los guiones gráficos aportan algunas ventajas, creo que no hay ninguna desventaja razonable que pondría en una lista para desalentar el uso del código (excepto, quizás, la pereza).

Un proyecto, múltiples herramientas

Los guiones gráficos, los NIB y el código son tres herramientas diferentes para crear la interfaz de usuario de iOS. Tenemos suerte de tenerlos. Los fanáticos de las interfaces de usuario programáticas probablemente no tendrán en cuenta las otras dos opciones: el código te permite hacer todo lo que es técnicamente posible, mientras que las alternativas tienen sus limitaciones. Para el resto de los desarrolladores, la navaja Xcode proporciona tres herramientas que se pueden usar todas a la vez, en el mismo proyecto, de manera efectiva.

¿Cómo, preguntas? Como sea que te guste. Aquí hay algunos enfoques posibles:

  • Agrupe todas las pantallas relacionadas en grupos separados e implemente cada grupo con su propio guión gráfico distinto.
  • Diseñe celdas de tabla no reutilizables en el lugar con un Storyboard, dentro del controlador de vista de tabla.
  • Diseñe celdas de tabla reutilizables en NIB para fomentar la reutilización y evitar la repetición, pero cargue estas NIB a través de un código personalizado.
  • Diseñe vistas personalizadas, controles y objetos intermedios utilizando NIB.
  • Utilice código para vistas muy dinámicas y, de forma más general, para vistas que no se pueden implementar fácilmente a través de guiones gráficos y NIB, mientras aloja las transiciones de vista en un guión gráfico.

Para cerrar, veamos un último ejemplo que une todo.

Un caso de uso simple

Digamos que queremos desarrollar una aplicación de mensajería básica con varias vistas diferentes:

  • Una lista de amigos seguidos (con una plantilla de celda reutilizable para mantener la interfaz de usuario coherente en futuras listas).
  • Una vista detallada del perfil, compuesta en secciones separadas (que incluyen información del perfil, estadísticas y una barra de herramientas).
  • Una lista de mensajes enviados y recibidos de un amigo.
  • Un nuevo formulario de mensaje.
  • Una vista de nube de etiquetas que muestra las diferentes etiquetas utilizadas en los mensajes de los usuarios, con cada etiqueta proporcional en tamaño a la cantidad de veces que se ha utilizado.

Además, queremos que las vistas fluyan de la siguiente manera:

  • Al hacer clic en un elemento de la lista de amigos seguidos, se muestran los detalles del perfil del amigo correspondiente.
  • Los detalles del perfil muestran el nombre del perfil, la dirección, las estadísticas, una breve lista de los mensajes más recientes y una barra de herramientas.

Para implementar esta aplicación de iOS, nuestras tres herramientas de interfaz de usuario serán útiles, ya que podemos usar:

  • Un guión gráfico con cuatro controladores de vista (la lista, los detalles, la lista de mensajes y el formulario de mensaje nuevo).
  • Un archivo NIB separado para la plantilla de celda de lista de perfil reutilizable.
  • Tres archivos NIB separados para la vista de detalles del perfil, uno para cada una de las secciones separadas que lo componen (detalles del perfil, estadísticas, últimos tres mensajes), para permitir una mejor capacidad de mantenimiento. Estos NIB se instanciarán como vistas y luego se agregarán al controlador de vista.
  • Código personalizado para la vista de nube de etiquetas. Esta vista es un ejemplo típico de una que no se puede diseñar en Interface Builder, ni mediante StoryBoards ni NIB. En cambio, se implementa completamente a través del código. Para mantener el flujo visual del Guión gráfico, elegimos agregar un controlador de vista vacío al Guión gráfico, implementar la vista de nube de etiquetas como una vista independiente y agregar mediante programación la vista al controlador de vista. Claramente, la vista también podría implementarse dentro del controlador de vista en lugar de como una vista independiente, pero las mantenemos separadas para una mejor reutilización.

Una maqueta realmente básica podría verse así:

Este diagrama ilustra un proyecto de diseño de interfaz de usuario de iOS que utiliza guiones gráficos, NIB y código de iOS personalizado.

Con eso, hemos esbozado la construcción básica de una aplicación de iOS razonablemente sofisticada cuyas vistas centrales unen nuestros tres enfoques principales para el diseño de la interfaz de usuario. Recuerde: no se debe tomar una decisión binaria, ya que cada herramienta tiene sus fortalezas y debilidades.

Terminando

Como se examinó en este tutorial, los guiones gráficos agregan una simplificación notable al diseño de la interfaz de usuario de iOS y al flujo visual. También eliminan el código repetitivo; pero todo esto tiene un precio, pagado en flexibilidad. Mientras tanto, los NIB ofrecen más flexibilidad al enfocarse en una sola vista, pero sin flujo visual. La solución más flexible, por supuesto, es el código, que tiende a ser poco amigable e inherentemente no visual.

Si este artículo le intrigó, le recomiendo ver el gran debate de Ray Wenderlich, 55 minutos bien invertidos en una discusión sobre NIB, guiones gráficos y UIS creados con código.

Para terminar, quiero enfatizar una cosa: evite usar la herramienta de diseño de interfaz de usuario de iOS inadecuada a toda costa . Si una vista no se puede diseñar con un guión gráfico, o si se puede implementar con NIB o código de una forma más sencilla, no utilice un guión gráfico. Del mismo modo, si una vista no se puede diseñar con NIB, no utilice NIB. Estas reglas, si bien son simples, contribuirán en gran medida a su educación como desarrollador.