Interface Builder: o que é, design visual no Xcode e storyboards

Autor: IT Sectr Publicado: 2026-02-12 Tempo de leitura: 15 min

Interface Builder é um editor visual de interfaces integrado ao Xcode para desenvolvimento iOS e macOS. Permite criar UI através de arrastar e soltar, configurar Auto Layout e conectar código via IBOutlet e IBAction. Vamos analisar como o IB funciona, as diferenças entre Storyboard e XIB, e por que o @IBDesignable é necessário.

Principais pontos

  • Interface Builder — um editor visual no Xcode para interfaces UIKit sem escrever código de layout
  • Storyboard descreve várias telas e transições entre elas; XIB — um componente ou tela
  • Auto Layout no IB define restrições através dos menus Pin, Align e Resolve Issues
  • IBOutlet e IBAction conectam código Swift a elementos de UI via Ctrl+arrastar
  • @IBDesignable e @IBInspectable exibem visualizações personalizadas diretamente na tela do IB

O que é Interface Builder?

Interface Builder é um componente do Xcode projetado para o design visual de interfaces de usuário. A história do IB começou em 1988 na NeXT, muito antes do surgimento do iOS. Stefan Pope desenvolveu a primeira versão para o NeXTSTEP — o sistema operacional que se tornou a base do macOS e iOS. Em 1996, a Apple adquiriu a NeXT e integrou o Interface Builder ao Xcode.

No Xcode moderno, o Interface Builder suporta três formatos de arquivo: Storyboard, XIB (Xcode Interface Builder) e arquivos XIB para células de tabela e visualizações personalizadas. Cada um desses formatos armazena uma descrição XML da hierarquia de elementos da UI, suas propriedades, restrições e conexões com o código.

O IB funciona ao nível do UIKit: botões, rótulos, campos de texto, tabelas, coleções e restrições são arrastados com o mouse para a tela. O Xcode compila arquivos .storyboard e .xib em arquivos nib (Interface Builder compilado) durante a compilação, o que reduz o tamanho do pacote e acelera o carregamento.

Segundo a Apple, mais de 70% dos projetos iOS em UIKit usam o Interface Builder em diferentes estágios de desenvolvimento. Apesar do crescimento do SwiftUI, o IB continua sendo o padrão para aplicações comerciais que suportam iOS 12 e versões anteriores, bem como para interfaces personalizadas complexas que exigem configuração detalhada do Auto Layout.

Como o Interface Builder chegou ao Xcode

Antes do Xcode 4, o Interface Builder era um aplicativo separado executado paralelamente ao editor de código. No Xcode 4 (2011), a Apple fundiu o IB e o editor de código em um único IDE. Isso permitiu alternar entre código e layout sem trocar de janela e ver alterações de propriedades em tempo real através do painel Attributes Inspector.

Versão do XcodeAnoMudanças no Interface Builder
Xcode 32008IB — aplicativo separado, suporte iOS 2.0
Xcode 42011IB integrado ao IDE, surgimento do Storyboard
Xcode 52013Auto Layout com menu de restrições, pré-visualização de telas
Xcode 62014Size Classes, @IBDesignable, Preview Assistant
Xcode 112019SwiftUI Canvas, IB permanece para UIKit
Xcode 152023SwiftUI Preview como ferramenta principal, modo legado do IB

Com a introdução do SwiftUI em 2019, a Apple mudou o foco para o desenvolvimento declarativo, no entanto o Interface Builder permanece integrado ao Xcode para suportar projetos UIKit. Milhares de aplicações existentes continuam a usar o IB, e a Apple não anunciou sua remoção.

Storyboard e XIB: formatos de arquivo do IB

O Interface Builder suporta dois formatos principais: Storyboard (.storyboard) e XIB (.xib). A diferença entre eles está no escopo e no caso de uso.

Storyboard é um arquivo que contém toda a cena da aplicação: várias telas (UIViewController), transições entre elas (segues), controladores de navegação, barras de guias e todos os elementos da UI. Um Storyboard é carregado uma vez na inicialização a partir do Info.plist através da chave UIMainStoryboardFile (k). Isso é conveniente para visualizar o fluxo de telas, mas cria problemas com conflitos de merge no git, já que a descrição XML de toda a aplicação é armazenada em um único arquivo.

XIB (significa Xcode Interface Builder) é um arquivo para um único componente: uma UIView individual, UITableViewCell, UICollectionViewCell ou um ViewController. O XIB é carregado sob demanda através de UINib(nibName:bundle:) (k) ou do método Bundle.loadNibNamed (k). Arquivos XIB são mais fáceis de mesclar, mais compactos e carregam mais rápido, pois não contêm a descrição de toda a aplicação.

CritérioStoryboardXIB
EscopoVárias telas + transiçõesUma tela ou componente
SeguesSuporta (push, modal, unwind)Não suporta
Merge no gitDifícil (um XML grande)Simples (muitos arquivos pequenos)
CarregamentoAo iniciar a aplicaçãoSob demanda (preguiçoso)
ReutilizaçãoApenas através de referências de storyboardAlta (células, cabeçalhos, visualizações)
Recomendação da AppleNão recomendado para projetos grandesRecomendado para componentes

Desde o Xcode 11, a Apple recomenda usar XIB para componentes individuais e evitar Storyboards monolíticos. Para navegação entre telas, prefere-se a navegação baseada em código através de UIStoryboardSegue (k) manualmente ou coordenadores.

Estrutura XML em arquivos IB

Arquivos .storyboard e .xib armazenam XML no formato Interface Builder Cocoa Touch XIB (dt). Exemplo de uma estrutura simplificada:

xml
<!-- XIB file with UIView and UILabel -->
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB"
          version="3.0">
  <objects>
    <view id="abc-123"
          userLabel="CustomHeaderView"
          contentMode="scaleToFill">
      <subviews>
        <label id="def-456"
               text="Title"
               textColor="darkTextColor"
               fontDescription="title1"/>
      </subviews>
    </view>
  </objects>
</document>

Cada elemento tem um id (an) único, pelo qual o IB liga o nó XML ao objeto em tempo de execução. Durante a compilação, o Xcode converte o XML em formato nib binário (.nib), reduzindo o tamanho do arquivo em aproximadamente 40%.

Auto Layout e Size Classes no Interface Builder

Auto Layout é um sistema para posicionar elementos na tela através de relações matemáticas (restrições). O Interface Builder fornece uma interface visual para criar, editar e depurar restrições sem escrever código. Cada restrição descreve uma dependência: view.leading = superview.leading + 16 (k) ou view.width = 2 * otherView.height (k).

No IB, as restrições são criadas através do menu Pin (fixar margens, largura, altura) e do menu Align (centralizar, bordas, linha de base). O painel Size Inspector mostra todas as restrições do elemento selecionado, suas prioridades (required/high/low) e permite editar multiplicadores e constantes.

O IB também suporta UIStackView — um contêiner que gerencia automaticamente o layout das visualizações filhas. Basta colocar elementos em uma pilha na tela, e o IB gerará as restrições necessárias automaticamente. Isso acelera significativamente o layout em comparação com a colocação manual de restrições.

Size Classes: adaptação a dispositivos

Size Classes são uma abstração que agrupa dispositivos por largura e altura da tela: Compact e Regular. As combinações (wC hR para iPhone retrato, wR hR para iPad) permitem especificar diferentes restrições e layouts de elementos para diferentes cenários. No Interface Builder, alternar entre size classes altera o conjunto de restrições ativas na tela.

DispositivoOrientaçãoWidth ClassHeight Class
iPhone (exceto Max/Plus)RetratoCompactRegular
iPhone (exceto Max/Plus)PaisagemCompactCompact
iPhone Plus/MaxPaisagemRegularCompact
iPadQualquerRegularRegular
iPad Split View1/3 da telaCompactRegular

Exemplo de uma restrição com variação de size class:

swift
import UIKit

class AdaptiveViewController: UIViewController {

    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var leadingConstraint: NSLayoutConstraint!

    private func updateConstraints() {
        let isRegular = traitCollection.horizontalSizeClass == .regular
        leadingConstraint.constant = isRegular ? 40 : 16
        titleLabel.font = isRegular
            ? UIFont.preferredFont(forTextStyle: .largeTitle)
            : UIFont.preferredFont(forTextStyle: .title1)
    }

    override func traitCollectionDidChange(
        _ previousTraitCollection: UITraitCollection?
    ) {
        super.traitCollectionDidChange(previousTraitCollection)
        if traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass {
            updateConstraints()
        }
    }
}

No código acima, traitCollectionDidChange reage à alteração de size class, atualizando a restrição e a fonte. O Interface Builder permite definir valores padrão para cada size class através do inspetor, enquanto o código é usado para cenários dinâmicos que não podem ser descritos estaticamente.

IBOutlet, IBAction e conexão do código com a UI

A conexão entre a interface visual no Interface Builder e o código Swift/Objective-C é feita através de dois mecanismos: IBOutlet (Interface Builder Outlet) e IBAction (Interface Builder Action). Ambos são criados arrastando com a tecla Ctrl pressionada da tela do IB para o arquivo do controlador.

IBOutlet é uma anotação que declara uma referência a um elemento da UI. O Xcode a conecta automaticamente ao objeto correspondente no arquivo nib ao carregar. Se a conexão for quebrada (por exemplo, um elemento for renomeado), a aplicação falha com um erro NSUnknownKeyException (k). IBOutlet é marcado como weak (k), já que o nib possui o objeto e o controlador é apenas um observador.

IBAction é um método chamado em um evento de elemento da UI: pressionar botão, alterar texto, alternar interruptor. O IB conecta UIControlEvent (k) ao método através de addTarget:action:forControlEvents: (k). No código, IBAction parece um método normal com tipo de retorno IBAction (dt).

swift
import UIKit

final class LoginViewController: UIViewController {

    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var loginButton: UIButton!
    @IBOutlet weak var spinner: UIActivityIndicatorView!

    @IBAction private func loginButtonTapped(_ sender: UIButton) {
        guard let email = emailTextField.text, !email.isEmpty,
              let password = passwordTextField.text, !password.isEmpty
        else {
            showAlert(message: "Fill in all fields")
            return
        }
        loginButton.isEnabled = false
        spinner.startAnimating()
        performLogin(email: email, password: password)
    }

    private func performLogin(email: String, password: String) {
        /// API call via URLSession
        let request = LoginRequest(email: email, password: password)
        APIClient.shared.login(request) { [weak self] result in
            DispatchQueue.main.async {
                guard let self else { return }
                self.spinner.stopAnimating()
                self.loginButton.isEnabled = true
                switch result {
                case .success:
                    self.navigateToMainScreen()
                case .failure(let error):
                    self.showAlert(message: error.localizedDescription)
                }
            }
        }
    }

    private func showAlert(message: String) {
        let alert = UIAlertController(
            title: "Error",
            message: message,
            preferredStyle: .alert
        )
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}

O exemplo mostra uma configuração padrão: IBOutlet para campos de texto, botão e spinner, IBAction para lidar com o toque. Todas essas conexões são definidas no Interface Builder através de Ctrl+arrastar. Se a conexão não estiver configurada, o IBOutlet será nil (v) em tempo de execução, causando uma falha no acesso — por isso o IBOutlet é declarado como weak var (k s) com desembrulho implícito.

@IBDesignable e @IBInspectable: componentes personalizados

@IBDesignable é uma anotação Swift que permite exibir uma UIView personalizada diretamente na tela do Interface Builder em tempo real. O desenvolvedor vê as alterações de código sem executar a aplicação. @IBInspectable é uma anotação para propriedades, adicionando-as ao painel Attributes Inspector do IB, onde os valores podem ser alterados interativamente.

Essas anotações são especialmente úteis ao criar bibliotecas de componentes de UI: botões personalizados, campos de entrada com máscara, indicadores animados. O IBDesignable usa prepareForInterfaceBuilder() (fn) para compilação separada do código de construção, sem afetar o binário principal da aplicação.

swift
import UIKit

@IBDesignable
final class GradientButton: UIButton {

    @IBInspectable var startColor: UIColor = .systemBlue {
        didSet { updateGradient() }
    }

    @IBInspectable var endColor: UIColor = .systemPurple {
        didSet { updateGradient() }
    }

    @IBInspectable var cornerRadius: CGFloat = 12 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = true
        }
    }

    private let gradientLayer = CAGradientLayer()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupGradient()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupGradient()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        gradientLayer.frame = bounds
    }

    private func setupGradient() {
        layer.insertSublayer(gradientLayer, at: 0)
        updateGradient()
    }

    private func updateGradient() {
        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        setupGradient()
    }
}

No código acima, GradientButton é um componente IBDesignable com propriedades IBInspectable startColor (v), endColor (v) e cornerRadius (v). Ao arrastar uma UIView para a tela do IB e alterar a classe para GradientButton no Identity Inspector, um botão com gradiente será exibido na tela em tempo real. Todas as propriedades IBInspectable aparecerão no painel Attributes Inspector à direita.

Importante: @IBDesignable compila todo o código para exibição no IB, portanto, solicitações de rede ou operações longas não devem ser executadas dentro dele. Para separação, usa-se #if TARGET_INTERFACE_BUILDER (k) — compilação condicional que exclui o código não destinado ao IB.

Ciclo de vida dos arquivos IB durante a compilação

O processo de transformação dos arquivos do Interface Builder desde a criação do nib até a exibição na tela inclui várias etapas. Compreender este ciclo ajuda a diagnosticar problemas relacionados ao IB.

Na etapa de compilação, o Xcode executa a ferramenta ibtool (k, fn) — um utilitário de linha de comando para compilar arquivos .storyboard e .xib em formato nib binário. O ibtool também realiza validação: verifica a correção das restrições, a existência de todas as classes, os tipos de conexão IBOutlet/IBAction. Erros de validação são exibidos no Issue Navigator do Xcode.

O arquivo .nib final é colocado no pacote da aplicação na pasta .nib (s). O tamanho do arquivo nib é significativamente menor que o XML original: o formato binário usa uma representação otimizada com substituição de strings por tokens e compressão de valores numéricos. A compressão típica é de 50–60% do tamanho XML original.

Em tempo de execução, o nib é carregado através de UINib(nibName:bundle:) (k) ou automaticamente através de UIStoryboard.instantiateViewController(withIdentifier:) (k). O processo de carregamento inclui:

  • Desserialização do nib binário em um grafo de objetos Objective-C/Swift
  • Criação de instâncias de todos os elementos da UI do arquivo
  • Restauração de conexões IBOutlet e IBAction (outletCollection para grupos)
  • Aplicação de restrições do Auto Layout do arquivo considerando a size class
  • Chamada a awakeFromNib() (fn) para cada objeto — ponto de entrada para configuração pós-carregamento

O método awakeFromNib() (fn) é chamado depois que todos os IBOutlets já estão definidos, mas antes do primeiro layoutSubviews. Isso é conveniente para configuração inicial: arredondar cantos, adicionar sombras, localizar texto. No entanto, todos os IBOutlets são garantidamente não-nil no awakeFromNib.

Interface Builder vs SwiftUI Preview

Com o lançamento do SwiftUI em 2019, os desenvolvedores iOS ganharam uma alternativa ao Interface Builder — um framework declarativo com Canvas Preview em tempo real. Vamos analisar as principais diferenças entre as duas abordagens.

Interface Builder gera uma descrição XML que é compilada em nib. A interface é criada visualmente; o código lida apenas com a lógica. O IB requer um limiar de entrada mais baixo para designers sem habilidades de programação, mas é difícil para revisão de código (alterações XML não são visíveis no diff).

SwiftUI Preview é desenvolvimento totalmente baseado em código. A interface é descrita em Swift, a pré-visualização é atualizada a cada salvamento. Sem XML, sem nib, sem risco de conexões IBOutlet quebradas. O SwiftUI Preview funciona mais rápido que o IB, pois não requer compilar um arquivo separado.

CritérioInterface Builder (UIKit)SwiftUI Preview
Formato de arquivoXML (.storyboard / .xib) → nib binárioCódigo Swift (sem arquivo intermediário)
Pré-visualizaçãoTela do IB com atraso para visualizações complexasCanvas Preview em tempo real
Suporte a versões iOSiOS 2.0+ (todas as versões)iOS 13+
Merge no gitProblemático (um arquivo XML)Simples (código Swift normal)
Dados dinâmicosAtravés de IBOutlet + código@State (k), @Observable (k)
Visualizações personalizadas@IBDesignable (compilação)SwiftUI View com PreviewProvider
DesempenhoCarregamento rápido de nibCompilação Swift sob demanda

Na prática, a escolha entre IB e SwiftUI Preview depende dos requisitos do projeto. Interface Builder é indispensável para aplicações UIKit com suporte a versões antigas do iOS, bem como para projetos comerciais onde designers trabalham no Xcode sem habilidades em Swift. O SwiftUI é preferível para novos projetos direcionados ao iOS 17+, onde a velocidade de desenvolvimento e a reatividade são importantes.

A Apple não planeja remover o Interface Builder do Xcode. Além disso, no Xcode 16, a empresa melhorou o desempenho da tela do IB e adicionou suporte a componentes SwiftUI através do UIViewRepresentable Bridge. Espera-se que o IB seja suportado pelo menos até 2030.

Melhores práticas para trabalhar com Interface Builder

Anos de experiência em desenvolvimento iOS formaram um conjunto de recomendações que reduzem o número de problemas ao usar o Interface Builder em projetos comerciais.

Use XIB em vez de Storyboard para componentes reutilizáveis. Cada célula de tabela personalizada, cabeçalho ou rodapé deve estar em um XIB separado. Isso facilita o merge, acelera o carregamento e permite reutilizar componentes entre projetos através do Swift Package Manager ou CocoaPods.

Configure Storyboard References para dividir storyboards grandes em módulos. Em vez de um Main.storyboard com 100 telas, crie um storyboard para cada módulo (Auth, Profile, Feed) e conecte-os através de Storyboard Reference. Isso reduzirá o tempo de compilação do ibtool e simplificará o trabalho em equipe.

Evite conexões IBOutlet para File's Owner (k) sem verificação. Cada conexão deve ser weak (k) e opcional (o opcional implicitamente desembrulhado só é ótimo em playgrounds). Ao renomear um IBOutlet em uma visualização, o Xcode atualiza automaticamente a conexão, mas a edição manual de XML pode facilmente introduzir erros.

  • Verifique sempre o Show Connection Panel (k) após editar um arquivo IB — indicadores vermelhos sinalizam conexões quebradas
  • Use User Defined Runtime Attributes (k) para definir propriedades sem código: layer.cornerRadius, layer.borderWidth, tintColor
  • Agrupe restrições no IB por propósito: restrições para tamanhos, restrições para margens, restrições para proporções
  • Atribua um Identifier (k) a cada restrição no Size Inspector — isso ajuda a depurar conflitos
  • Não coloque lógica de negócios no awakeFromNib — apenas configuração de UI. A lógica vai no viewDidLoad ou em serviços separados
swift
import UIKit

final class ProfileHeaderView: UIView {

    @IBOutlet weak var avatarImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var bioLabel: UILabel!
    @IBOutlet weak var editButton: UIButton!

    override func awakeFromNib() {
        super.awakeFromNib()
        avatarImageView.layer.cornerRadius = avatarImageView.bounds.width / 2
        avatarImageView.layer.masksToBounds = true
        nameLabel.font = UIFont.preferredFont(forTextStyle: .headline)
        bioLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
    }

    func configure(with profile: UserProfile) {
        nameLabel.text = profile.fullName
        bioLabel.text = profile.bio
        /// Loading avatar via SDWebImage or Kingfisher
    }

    static func instantiateFromNib() -> ProfileHeaderView {
        let nib = UINib(nibName: String(describing: self), bundle: nil)
        return nib.instantiate(withOwner: nil).first as! ProfileHeaderView
    }
}

O exemplo mostra uma melhor prática para visualizações XIB: um método estático instantiateFromNib (fn) carrega a visualização do XIB com o mesmo nome da classe. O método awakeFromNib (fn) configura a UI (cantos arredondados, fontes), e o método configure(with:) (fn) aceita um modelo de dados para preenchimento. A separação de responsabilidades simplifica os testes e a reutilização.

Perguntas frequentes

Como o Interface Builder difere do SwiftUI Preview?

Interface Builder é um editor visual para UIKit com formato Storyboard/XIB, funcionando através de arrastar e soltar. SwiftUI Preview é uma pré-visualização declarativa em tempo real onde a interface é descrita em código Swift. Ambas as ferramentas estão integradas no Xcode, mas o IB gera XML enquanto o SwiftUI compila Swift diretamente. O IB suporta iOS 2.0+, o SwiftUI suporta iOS 13+.

Posso usar o Interface Builder com SwiftUI?

Não, o Interface Builder não é diretamente compatível com o SwiftUI. O SwiftUI usa sua própria sintaxe declarativa e Canvas Preview. No entanto, projetos UIKit criados através do IB podem ser integrados ao SwiftUI via UIViewRepresentable, e visualizações SwiftUI podem ser incorporadas ao UIKit via UIHostingController. Isso permite migrar gradualmente do IB para o SwiftUI.

O que são @IBDesignable e @IBInspectable?

@IBDesignable é uma anotação Swift que exibe uma UIView personalizada diretamente no Interface Builder em tempo real sem executar a aplicação. @IBInspectable é uma anotação para propriedades, adicionando-as ao painel Attributes Inspector do IB. Ambas as anotações aceleram o desenvolvimento de componentes de UI personalizados: basta alterar uma propriedade no inspetor e a mudança é imediatamente visível na tela.

Como o Auto Layout funciona no Interface Builder?

O Auto Layout no Interface Builder define restrições através do menu Pin (margens, largura, altura) e do menu Align (centralização, linha de base). Cada restrição é uma relação matemática entre visualizações. O IB exibe erros com linhas vermelhas e conflitos com avisos amarelos. As Size Classes no IB permitem especificar diferentes restrições para diferentes dispositivos e orientações sem escrever código.

Como conectar código com o Interface Builder via IBOutlet e IBAction?

IBOutlet é uma anotação para uma referência a um elemento da UI a partir do código (por exemplo, @IBOutlet weak var label: UILabel!). IBAction é uma anotação para um método chamado em um evento (por exemplo, @IBAction func buttonTapped(_ sender: UIButton)). A conexão é criada através de Ctrl+arrastar da tela do IB para o arquivo do controlador. O Xcode gera automaticamente o código de conexão ao soltar o mouse.

Resumo

  • Interface Builder — um editor visual no Xcode para UIKit com história desde 1988 (NeXTSTEP)
  • Storyboard é adequado para prototipagem, XIB para componentes reutilizáveis e projetos de produção
  • Auto Layout e Size Classes no IB permitem criar interfaces adaptativas sem código
  • IBOutlet e IBAction conectam código à UI através de Ctrl+arrastar com geração automática de propriedades Swift
  • @IBDesignable e @IBInspectable aceleram o desenvolvimento de visualizações personalizadas com pré-visualização no IB
  • SwiftUI Preview está substituindo o IB para novos projetos, mas o IB continua sendo o padrão para UIKit legado
  • Melhores práticas: XIB em vez de Storyboard, weak IBOutlet, identificação de restrições, separação de awakeFromNib e configuração

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também