Interfaces de usuário do iOS: storyboards x NIBs x código personalizado
Publicados: 2022-03-11Costumo ouvir os desenvolvedores do iOS fazerem alguma variante da mesma pergunta-chave:
Qual é a melhor maneira de desenvolver uma interface do usuário no iOS: por meio de storyboards, NIBs ou código?
As respostas a essa pergunta, explícita ou implicitamente, tendem a supor que há uma escolha mutuamente exclusiva a ser feita, que geralmente é abordada antecipadamente, antes do desenvolvimento.
Sou da opinião de que a resposta deve assumir a forma de uma ou mais contra -perguntas.
Qual é o “melhor” carro?
Deixe-me explicar com um exemplo off-topic. Digamos que eu queira comprar um carro e eu faça uma pergunta simples: “Qual é a melhor escolha?”
Você pode realmente responder sugerindo um modelo, ou mesmo uma marca? Não é provável, a menos que você sugira uma Ferrari. Em vez disso, você provavelmente responderia com algumas outras perguntas, como:
- Qual é o seu orçamento?
- De quantos assentos você precisa?
- Você se preocupa com o consumo de combustível?
- Como você se sente sobre carros esportivos?
É óbvio que não existe um carro bom ou ruim a menos que seja colocado em um contexto adequado – existe apenas um carro bom ou ruim baseado em necessidades específicas.
Voltar para o design de interface do iOS
Assim como em nossa consulta sobre carros, a pergunta “Qual é a melhor maneira de desenvolver uma interface de usuário do iOS” carece de contexto. E surpreendentemente, a resposta não precisa ser um caso abrangente.
De um modo geral, existem três tipos de abordagens de design de interface de usuário que você pode adotar, cada uma com seus prós e contras, seus fãs e inimigos:
- iOS Storyboards : Uma ferramenta visual para apresentar várias visualizações de aplicativos e as transições entre elas.
- NIBs (ou XIBs) : Cada arquivo NIB corresponde a um único elemento de visualização e pode ser disposto no Interface Builder, tornando-o também uma ferramenta visual. Observe que o nome “NIB” é derivado da extensão do arquivo (anteriormente .nib e agora .xib, embora a pronúncia antiga tenha persistido).
- Código personalizado : ou seja, nenhuma ferramenta GUI, mas sim, manipulação de todo o posicionamento personalizado, animação, etc. programaticamente.
Nenhuma dessas opções é universalmente melhor do que qualquer outra (apesar do que você pode ouvir).
Os storyboards, por exemplo, são a mais recente adição ao kit de ferramentas da interface do usuário do iOS. Disseram-me que eles são o futuro, que substituirão NIBs e UIs de código personalizado. Vejo os Storyboards como uma ferramenta útil, mas não tanto como um substituto quanto um complemento para NIBs e código personalizado. Os storyboards são a escolha certa em algumas, mas não em todas as situações.
Além disso, por que você deveria se ater estaticamente a uma única opção quando você pode usar todas elas (no mesmo projeto), escolhendo o mecanismo que melhor se adapta ao problema específico em questão?
Esta é uma pergunta que pode ser, na minha opinião, generalizada em um nível mais alto, e cuja resposta está bem classificada na minha lista de princípios de desenvolvimento de software: Não existe linguagem, framework ou tecnologia universal que seja a melhor escolha universal para cada problema de desenvolvimento de software. O mesmo vale para o design da interface do usuário do iOS.
Neste tutorial de desenvolvimento para iOS, vamos explorar cada um desses métodos e apresentar casos de uso em que eles devem e não devem ser empregados, bem como maneiras de combiná-los.
Storyboards para iOS
O erro clássico de um iniciante é criar um enorme Storyboard iOS em todo o projeto. Eu também cometi esse erro quando comecei a trabalhar com Storyboards (provavelmente porque é um caminho tentador).
Como o próprio nome indica, um Storyboard é um quadro com uma história para contar . Não deve ser usado para misturar histórias não relacionadas em um grande volume. Um storyboard deve conter controladores de exibição que são logicamente relacionados entre si, o que não significa todos os controladores de exibição.
Por exemplo, faz sentido usar Storyboards ao lidar com:
- Um conjunto de visualizações para autenticação e registro.
- Um fluxo de entrada de pedidos em várias etapas.
- Um fluxo de assistente (ou seja, tutorial).
- Um conjunto de visualizações de detalhes mestre (por exemplo, listas de perfis, detalhes de perfis).
Enquanto isso, grandes storyboards devem ser evitados, incluindo storyboards únicos em todo o aplicativo (a menos que o aplicativo seja relativamente simples). Antes de irmos mais fundo, vamos ver o porquê.
A loucura dos grandes storyboards iOS
Storyboards grandes, além de serem difíceis de navegar e manter, adicionam uma camada de complexidade a um ambiente de equipe: quando vários desenvolvedores trabalham no mesmo arquivo de storyboard ao mesmo tempo, os conflitos de controle de origem são inevitáveis . E enquanto um storyboard é representado internamente como um arquivo de texto (um arquivo XML, na verdade), a mesclagem geralmente não é trivial.
Quando os desenvolvedores visualizam o código-fonte, eles atribuem significado semântico a ele. Portanto, ao mesclar manualmente, eles podem ler e entender os dois lados de um conflito e agir de acordo. Um storyboard, em vez disso, é um arquivo XML gerenciado pelo Xcode, e o significado de cada linha de código nem sempre é fácil de entender.
Vamos dar um exemplo muito simples: digamos que dois desenvolvedores diferentes mudem a posição de um UILabel
(usando autolayout), e o último empurra sua mudança, produzindo um conflito como este (observe os atributos id
conflitantes):
<layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides> <layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides>
O id
em si não fornece nenhuma indicação quanto ao seu verdadeiro significado, então você não tem nada com o que trabalhar. A única solução significativa é escolher um dos dois lados do conflito e descartar o outro. Haverá efeitos colaterais? Quem sabe? Você não.
Para aliviar esses problemas de design de interface do iOS, o uso de vários storyboards no mesmo projeto é a abordagem recomendada.
Quando usar storyboards
Os storyboards são melhor usados com vários controladores de exibição interconectados, pois sua maior simplificação está na transição entre os controladores de exibição. Até certo ponto, eles podem ser pensados como uma composição de NIBs com fluxos visuais e funcionais entre controladores de visão.
Além de facilitar o fluxo de navegação, outra vantagem distinta é que eles eliminam o código padrão necessário para pop, push, apresentar e dispensar controladores de exibição. Além disso, os controladores de exibição são alocados automaticamente, portanto, não há necessidade de alloc
e init
manualmente.
Por fim, embora os storyboards sejam melhor usados para cenários que envolvem vários controladores de exibição, também é defensável usar um storyboard ao trabalhar com um único controlador de exibição de tabela por três motivos:
- A capacidade de projetar protótipos de células de tabela no local ajuda a manter as peças juntas.
- Vários modelos de célula podem ser projetados dentro do controlador de exibição de tabela pai.
- É possível criar visualizações de tabela estáticas (uma adição muito aguardada que infelizmente só está disponível em Storyboards).
Pode-se argumentar que vários modelos de células também podem ser projetados usando NIBs. Na verdade, isso é apenas uma questão de preferência: alguns desenvolvedores preferem ter tudo em um só lugar, enquanto outros não se importam.
Quando não usar storyboards do iOS
Alguns casos:
- A exibição tem um layout complicado ou dinâmico, melhor implementado com código.
- A visualização já está implementada com NIBs ou código.
Nesses casos, podemos deixar a visualização fora do Storyboard ou incorporá-la em um controlador de visualização. O primeiro quebra o fluxo visual do Storyboard, mas não tem implicações funcionais ou de desenvolvimento negativas. O último retém esse fluxo visual, mas requer esforços de desenvolvimento adicionais, pois a exibição não está integrada ao controlador de exibição: é apenas incorporada como um componente, portanto, o controlador de exibição deve interagir com a exibição em vez de implementá-la.
Prós e contras gerais
Agora que temos uma noção de quando os storyboards são úteis no design da interface do usuário do iOS, e antes de passarmos para os NIBs neste tutorial, vamos analisar suas vantagens e desvantagens gerais.
Pró: Desempenho
Intuitivamente, você pode supor que, quando um Storyboard é carregado, todos os seus controladores de exibição são instanciados imediatamente. Felizmente, isso é apenas uma abstração e não é verdade para a implementação real: em vez disso, apenas o controlador de exibição inicial, se houver, é criado. Os outros controladores de visualização são instanciados dinamicamente, seja quando um segue é executado ou manualmente a partir do código.
Pro: Protótipos
Os storyboards simplificam a prototipagem e a maquete de interfaces de usuário e fluxo. Na verdade, um aplicativo protótipo funcional completo com visualizações e navegação pode ser facilmente implementado usando Storyboards e apenas algumas linhas de código.
Contra: Reutilização
Quando se trata de mover ou copiar, os Storyboards do iOS estão mal posicionados. Um Storyboard deve ser movido junto com todos os seus controladores de exibição dependentes. Em outras palavras, um único controlador de exibição não pode ser extraído e reutilizado individualmente em outro lugar como uma única entidade independente; depende do resto do Storyboard para funcionar.
Contra: fluxo de dados
Os dados geralmente precisam ser passados entre os controladores de exibição quando um aplicativo faz a transição. No entanto, o fluxo visual do Storyboard é interrompido neste caso, pois não há vestígios disso acontecendo no Interface Builder. Os storyboards cuidam do fluxo entre os controladores de exibição, mas não o fluxo de dados. Portanto, o controlador de destino deve ser configurado com código, substituindo a experiência visual.
Nesses casos, temos que contar com um prepareForSegue:sender
, com um 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 ... }
Acho essa abordagem propensa a erros e desnecessariamente detalhada.
NIBs
Os NIBs são a maneira mais antiga de executar o design da interface do iOS.
Nesse caso, “antigo” não significa “ruim”, “desatualizado” ou “obsoleto”. Na verdade, é importante entender que os storyboards do iOS não são um substituto universal para os NIBs; eles apenas simplificam a implementação da interface do usuário em alguns casos.
Com NIBs, qualquer visualização arbitrária pode ser projetada, que o desenvolvedor pode anexar a um controlador de visualização conforme necessário.
Se aplicarmos o design orientado a objetos às nossas UIs, faz sentido dividir a visão de um controlador de visão em módulos separados , cada um implementado como uma visão com seu próprio arquivo NIB (ou com vários módulos agrupados no mesmo arquivo). A clara vantagem dessa abordagem é que cada componente é mais fácil de desenvolver, mais fácil de testar e mais fácil de depurar.

Os NIBs compartilham os problemas de conflito de mesclagem que vimos com os Storyboards, mas em menor grau, pois os arquivos NIB operam em uma escala menor.
Quando usar NIBs para design de interface do iOS
Um subconjunto de todos os casos de uso seria:
- Visualizações modais
- Visualizações simples de login e registro
- Configurações
- Janelas pop-up
- Modelos de visualização reutilizáveis
- Modelos de célula de tabela reutilizáveis
Enquanto isso…
Quando não usar NIBs
Você deve evitar usar NIBs para:
- Visualizações com conteúdo dinâmico, onde o layout muda significativamente dependendo do conteúdo.
- Visualizações que, por natureza, não são facilmente projetáveis no Interface Builder.
- Visualize controladores com transições complicadas que podem ser simplificadas com o Storyboarding.
Prós e contras gerais
De maneira mais geral, vamos analisar os prós e contras do uso de NIBs.
Pró: Reutilização
Os NIBs são úteis quando o mesmo layout é compartilhado entre várias classes.
Como um caso de uso simples, um modelo de visualização contendo um nome de usuário e um campo de texto de senha pode ser implementado com as visualizações hipotéticas TTLoginView
e TTSignupView
, ambas originadas do mesmo NIB. O TTLoginView
teria que ocultar o campo de senha e ambos teriam que especificar rótulos estáticos correspondentes (como 'Digite seu nome de usuário' vs 'Digite sua senha'), mas os rótulos teriam a mesma funcionalidade básica e layouts semelhantes.
Prós e contras: desempenho
Os NIBs são carregados lentamente, então eles não usam memória até que precisem. Embora isso possa ser uma vantagem, há latência no processo de carregamento lento, tornando-o uma desvantagem também.
Código personalizado do iOS (IUs programáticas)
Qualquer design de interface iOS que possa ser feito com Storyboards e NIBs também pode ser implementado com código bruto (houve um tempo, é claro, em que os desenvolvedores não tinham o luxo de um conjunto tão rico de ferramentas).
Talvez mais importante, o que não pode ser feito com NIBs e Storyboards sempre pode ser implementado com código - desde, é claro, que seja tecnicamente viável. Outra maneira de ver isso é que NIBs e Storyboards são implementados com código, então sua funcionalidade será naturalmente um subconjunto. Vamos pular direto para os prós e contras.
Pró: sob o capô
A maior vantagem de criar uma interface do usuário do iOS programaticamente: se você sabe como codificar uma interface de usuário, sabe o que acontece nos bastidores , enquanto o mesmo não é necessariamente verdadeiro para NIBs e storyboards.
Para fazer uma comparação: uma calculadora é uma ferramenta útil. Mas não é ruim saber fazer cálculos manualmente.
Isso não se limita ao iOS, mas a qualquer ferramenta visual RAD (por exemplo, Visual Studio e Delphi, só para citar alguns). Ambientes visuais HTML RAD representam um caso típico de fronteira: eles são usados para gerar código (muitas vezes mal escrito), alegando que nenhum conhecimento de HTML é necessário e que tudo pode ser feito visualmente. Mas nenhum desenvolvedor da Web implementaria uma página da Web sem sujar as mãos: eles sabem que manipular manualmente o HTML e o CSS brutos levará a um código mais modular e mais eficiente.
Portanto, dominar a codificação das interfaces de usuário do iOS oferece mais controle e maior consciência de como essas peças se encaixam, o que aumenta seu limite superior como desenvolvedor.
Pró: quando o código é a única opção
Há também casos em que o código personalizado do iOS é a única opção para o design da interface do usuário. Layouts dinâmicos, onde os elementos de visualização são movidos e o fluxo ou layout se ajusta significativamente com base no conteúdo, são exemplos típicos.
Pró: Mesclar conflitos
Embora NIBs e Storyboards tenham sofrido significativamente com conflitos de mesclagem, o código não tem a mesma falha. Todo código tem significado semântico, então resolver conflitos não é mais difícil do que o normal.
Contra: Prototipagem
É difícil descobrir como um layout ficará até que você o veja em ação. Além disso, você não pode posicionar visualmente visualizações e controles, portanto, traduzir especificações de layout em uma visualização tangível pode levar muito mais tempo, em comparação com NIBs e Storyboards, que fornecem uma visualização imediata de como as coisas serão renderizadas.
Contra: Refatoração
Refatorar código que foi escrito há muito tempo ou por outra pessoa também se torna muito mais complicado: quando os elementos estão sendo posicionados e animados com métodos personalizados e números mágicos, as sessões de depuração podem se tornar árduas.
Pró: Desempenho
Em termos de desempenho, Storyboards e NIBs estão sujeitos à sobrecarga de carregamento e análise; e no final, eles são traduzidos indiretamente em código. Escusado será dizer que isso não acontece com UIs feitas por código.
Pró: Reutilização
Qualquer exibição implementada programaticamente pode ser projetada de maneira reutilizável. Vamos ver alguns casos de uso:
- Duas ou mais visualizações compartilham um comportamento comum, mas são ligeiramente diferentes. Uma classe base e duas subclasses resolvem o problema com elegância.
- Um projeto tem que ser bifurcado, com o objetivo de criar uma única base de código, mas gerar duas (ou mais) aplicações diferentes, cada uma com customizações específicas.
O mesmo processo de design de interface do usuário seria muito mais complicado com NIBs e Storyboards. Os arquivos de modelo não permitem herança e as soluções possíveis são limitadas ao seguinte:
- Duplique os arquivos NIB e Storyboard. Depois disso, eles têm vidas separadas e nenhuma relação com o arquivo original.
- Substitua a aparência e o comportamento pelo código, o que pode funcionar em casos simples, mas pode levar a complicações significativas em outros. Substituições pesadas com código também podem tornar o design visual inútil e evoluir para uma fonte constante de dores de cabeça, por exemplo, quando um determinado controle é exibido de uma maneira no Interface Builder, mas parece completamente diferente quando o aplicativo está em execução.
Quando usar o código
Geralmente, é uma boa opção usar o código personalizado para o design da interface do usuário do iOS quando você tem:
- Disposições dinâmicas.
- Vistas com efeitos, como cantos arredondados, sombras, etc.
- Qualquer caso em que o uso de NIBs e Storyboards seja complicado ou inviável.
Quando não usar o código
Em geral, as UIs feitas por código sempre podem ser usadas. Eles raramente são uma má ideia, então eu colocaria um
Embora NIBs e Storyboards tragam algumas vantagens para a mesa, sinto que não há desvantagem razoável que eu colocaria em uma lista para desencorajar o uso de código (exceto, talvez, preguiça).
Um projeto, várias ferramentas
Storyboards, NIBs e código são três ferramentas diferentes para construir a interface do usuário iOS. Temos sorte de tê-los. Os fanáticos por interfaces programáticas provavelmente não levarão em conta as outras duas opções: o código permite fazer tudo o que é tecnicamente possível, enquanto as alternativas têm suas limitações. Para o resto dos desenvolvedores, o canivete Xcode fornece três ferramentas que podem ser usadas de uma só vez, no mesmo projeto, de forma eficaz.
Como, você pergunta? Como você quiser. Aqui estão algumas abordagens possíveis:
- Agrupe todas as telas relacionadas em grupos separados e implemente cada grupo com seu próprio Storyboard distinto.
- Projete células de tabela não reutilizáveis no local com um Storyboard, dentro do controlador de exibição de tabela.
- Projete células de tabela reutilizáveis em NIBs para incentivar a reutilização e evitar a repetição, mas carregue esses NIBs por meio de código personalizado.
- Projete exibições, controles e objetos intermediários personalizados usando NIBs.
- Use o código para exibições altamente dinâmicas e, de modo mais geral, para exibições que não são facilmente implementáveis por meio de storyboards e NIBs, enquanto hospeda transições de exibição em um storyboard.
Para encerrar, vejamos um último exemplo que une tudo isso.
Um caso de uso simples
Digamos que queremos desenvolver um aplicativo de mensagens básico com várias visualizações diferentes:
- Uma lista de amigos seguidos (com um modelo de célula reutilizável para manter a IU consistente em listas futuras).
- Uma visualização de detalhes do perfil, composta em seções separadas (incluindo informações de perfil, estatísticas e uma barra de ferramentas).
- Uma lista de mensagens enviadas e recebidas de um amigo.
- Um novo formulário de mensagem.
- Uma visualização de nuvem de tags que exibe as diferentes tags usadas nas mensagens do usuário, com cada tag proporcional em tamanho ao número de vezes que foi usada.
Além disso, queremos que as visualizações fluam da seguinte forma:
- Clicar em um item na lista de amigos seguidos exibe os detalhes do perfil do amigo relevante.
- Os detalhes do perfil mostram o nome do perfil, endereço, estatísticas, uma pequena lista das mensagens mais recentes e uma barra de ferramentas.
Para implementar este aplicativo iOS, todas as três ferramentas de interface do usuário serão úteis, pois podemos usar:
- Um Storyboard com quatro controladores de visualização (a lista, detalhes, lista de mensagens e novo formulário de mensagem).
- Um arquivo NIB separado para o modelo de célula de lista de perfil reutilizável.
- Três arquivos NIB separados para a visualização de detalhes do perfil, um para cada uma das seções separadas que o compõem (detalhes do perfil, estatísticas, três últimas mensagens), para permitir melhor manutenção. Esses NIBs serão instanciados como visualizações e, em seguida, adicionados ao controlador de visualização.
- Código personalizado para a visualização da nuvem de tags. Essa visualização é um exemplo típico de uma que não pode ser projetada no Interface Builder, nem por meio de StoryBoards nem de NIBs. Em vez disso, é completamente implementado por meio de código. Para manter o fluxo visual do Storyboard, optamos por adicionar um controlador de visualização vazio ao Storyboard, implementar a visualização da nuvem de tags como uma visualização independente e adicionar programaticamente a visualização ao controlador de visualização. Claramente, a visualização também pode ser implementada dentro do controlador de visualização em vez de uma visualização independente, mas as mantemos separadas para melhor reutilização.
Uma maquete realmente básica pode se parecer com:
Com isso, descrevemos a construção básica de um aplicativo iOS razoavelmente sofisticado, cujas visualizações principais unem nossas três abordagens principais ao design de interface do usuário. Lembre-se: não há decisão binária a ser tomada, pois cada ferramenta tem seus pontos fortes e fracos.
Empacotando
Conforme examinado neste tutorial, os storyboards adicionam uma simplificação notável ao design da interface do usuário do iOS e ao fluxo visual. Eles também eliminam o código clichê; mas tudo isso tem um preço, pago em flexibilidade. Os NIBs, por sua vez, oferecem mais flexibilidade concentrando-se em uma única visualização, mas sem fluxo visual. A solução mais flexível, é claro, é o código, que tende a ser bastante hostil e inerentemente não visual.
Se este artigo o intrigou, eu recomendo assistir ao grande debate de Ray Wenderlich, 55 minutos bem gastos em uma discussão sobre NIBs, Storyboards e UIS feitos por código.
Para encerrar, quero enfatizar uma coisa: evite usar a ferramenta de design de interface do usuário do iOS imprópria a todo custo . Se uma visualização não puder ser projetada com um Storyboard ou se puder ser implementada com NIBs ou código de maneira mais simples, não use um Storyboard. Da mesma forma, se uma visualização não puder ser projetada usando NIBs, não use NIBs. Essas regras, embora simples, irão percorrer um longo caminho em sua educação como desenvolvedor.