Design de software

Injeção em Swift: construtor, propriedade ou método

Ao criar apps iOS com Swift, você inevitavelmente se depara com esta dúvida.

4 min de leitura
Imagem de capa de Injeção em Swift: construtor, propriedade ou método

Ao criar apps iOS com Swift, você inevitavelmente se depara com esta dúvida.

“Afinal, qual abordagem de injeção de dependência devo usar?”

Vou começar pela conclusão.

A menos que exista um motivo específico, a injeção pelo construtor (init) é o mais próximo da escolha certa.

Vou explicar o motivo e quando usar as outras duas abordagens, com base em experiência prática.


Três abordagens de injeção: o essencial primeiro

Antes de confundir as coisas, vamos estabelecer a base. No Swift, há três formas principais de fornecer dependências.

  1. Injeção pelo construtor (init)init recebe dependências como parâmetros
  2. Injeção por propriedadevar atribui depois à propriedade
  3. Injeção por método — injeta por meio de um método separado

Este é o código da abordagem mais recomendada: injeção pelo construtor.

final class OrderService {
    private let repo: MemberRepository // let garante a imutabilidade

    init(repo: MemberRepository) { // construtor(init) injeção
        self.repo = repo
    }
}

Como usa apenas a sintaxe nativa do Swift, sem bibliotecas extras, o código fica limpo.

Já a injeção por propriedade é curta assim.

final class OrderService {
    var repo: MemberRepository! // parece conveniente por ter uma linha só…
}

À primeira vista, a injeção por propriedade parece claramente mais simples. Mas essa conveniência pode trazer problemas depois.


Por que a injeção por propriedade é desaconselhada?

Vou começar por algo que vivenciei.

A injeção por propriedade é realmente incômoda nos testes. Se você esquecer de injetar depois de criar o objeto, ocorre um crash por forced unwrap, e o tipo, sozinho, não mostra o que precisa ser fornecido para completá-lo.

Com a injeção pelo construtor, você pode inserir diretamente um mock, como OrderService(repo: mockRepo), usando código Swift puro.

O segundo problema é não poder usar a palavra-chave let.

A injeção pelo construtor permite declarar as propriedades como let, tornando-as imutáveis depois da injeção.

Já a injeção por propriedade usa var, então o valor pode ser alterado a qualquer momento, abrindo espaço para erros.

O terceiro problema são as referências cíclicas.

Se A referencia B e B referencia A, a injeção por propriedade pode não revelar isso até o app ser executado. O problema só aparece ao entrar naquela tela.

A injeção pelo construtor revela o problema no momento da criação do objeto (e, se o design estiver confuso, ele pode nem compilar), permitindo corrigi-lo muito mais cedo.

Referências cíclicas falham em momentos diferentes
Referências cíclicas falham em momentos diferentes
Testar era trabalhoso quando eu usava apenas injeção por campo
Testar era trabalhoso quando eu usava apenas injeção por campo

Tabela comparativa de relance

Explicar em palavras pode confundir, então organizei tudo em uma tabela. (Diretriz da comunidade Swift em 2026)

Categoria Injeção pelo construtor (init) Injeção por propriedade Injeção por método
Imutabilidade (let) Possível ⭕ Impossível ❌ Impossível ❌
Facilidade para testes Alta Baixa Média
Detecção de referências cíclicas Imediata na criação Detectada tarde Detectada tarde
Dependência obrigatória/opcional Adequada para obrigatórias Distinção ambígua Adequada para opcionais
Concisão do código Média Muito concisa Média

A tendência fica clara só de olhar a tabela, não é?

A injeção pelo construtor se destaca na maioria dos critérios. Por isso, a documentação de bibliotecas de DI como Swinject e Factory também a recomenda como padrão.


Então, quando usar as outras duas abordagens?

Isso não significa que você deva usar sempre a injeção pelo construtor. Cada abordagem tem seu lugar.

A injeção por método combina bem com dependências opcionais.

Quando o alvo da injeção não é obrigatório — algo usado se estiver disponível, mas dispensável — você pode adicioná-lo com flexibilidade por um método como configure(with:).

A injeção por propriedade ainda pode fazer sentido quando não controlamos diretamente a inicialização, como em um view controller criado por storyboard.

No código comum da aplicação, é melhor evitá-la sempre que possível.

Em resumo:

  • Dependência obrigatória → injeção pelo construtor
  • Dependência opcional → injeção por método
  • Injeção por propriedade no código comum → evitar

Perguntas frequentes

P. Bibliotecas de DI como a Factory tornam a injeção pelo construtor mais fácil?

Sim. Ao registrar no Swinject ou na Factory como criar dependências, o container cria os objetos passados ao construtor. O código fica menor, preservando vantagens como a let imutabilidade.

P. E se o construtor ficar com parâmetros demais?

Isso não é um problema da abordagem de injeção, mas um sinal de que a classe está fazendo coisas demais. Primeiro, considere dividir as responsabilidades entre classes.

P. Uma biblioteca de DI é necessária até em projetos pequenos?

Não. Em um projeto com poucas telas, a injeção pelo construtor usando Swift puro, passando as dependências diretamente init, já é suficiente.

Quando estiver em dúvida, escolha nesta ordem
Quando estiver em dúvida, escolha nesta ordem

É fácil se sentir atraído pela praticidade da injeção por propriedade no início, mas, ao escrever testes e colaborar, você percebe na prática por que as vantagens da injeção pelo construtor são tão enfatizadas.

Se estiver em dúvida, comece pela injeção pelo construtor. Você agradecerá essa escolha à medida que o código crescer.