O que é Injeção de Dependência em Swift e por que é necessária?
\n\nInjeção de Dependência (DI) é um dos princípios-chave de design no desenvolvimento iOS moderno. Se você está apenas começando sua jornada em Swift, talvez já tenha se deparado com uma situação em que uma classe cria objetos de outra classe diretamente dentro de si. Isso é chamado de acoplamento rígido (tight coupling), e torna seu código difícil de testar e manter.
\n\nA Injeção de Dependência resolve esse problema: em vez de a classe criar suas próprias dependências, elas são "injetadas" externamente. Isso torna o código mais flexível, testável e alinhado ao princípio da Responsabilidade Única do SOLID.
\n\nNeste artigo, vamos explorar como a Injeção de Dependência funciona em Swift com exemplos práticos e mostrar como implementar essa prática em seus projetos para iOS e macOS.
\n\nPrincipais tipos de Injeção de Dependência em Swift
\n\nExistem três maneiras principais de injetar dependências em Swift. A escolha do método específico depende da arquitetura da sua aplicação.
\n\n1. Constructor Injection (Injeção via Inicializador)
\nA maneira mais comum e recomendada. As dependências são passadas através do init da classe. Isso garante que o objeto esteja sempre em um estado válido.
// Protocolo para o serviço\nprotocol DataServiceProtocol {\n func fetchData() -> String\n}\n\n// Implementação real\nclass DataService: DataServiceProtocol {\n func fetchData() -> String {\n return "Dados do servidor"\n }\n}\n\n// Classe que usa o serviço\nclass ViewModel {\n private let dataService: DataServiceProtocol\n \n // A dependência é injetada através do inicializador\n init(dataService: DataServiceProtocol) {\n self.dataService = dataService\n }\n \n func loadData() {\n let data = dataService.fetchData()\n print("Carregado: \\(data)")\n }\n}\n\n// Uso\nlet service = DataService()\nlet viewModel = ViewModel(dataService: service)\nviewModel.loadData()\n\n2. Property Injection (Injeção via Propriedade)
\nUsada quando a dependência não é obrigatória para o funcionamento do objeto ou pode mudar durante o ciclo de vida. É importante lembrar de definir a propriedade antes de usá-la.
\n\nclass NetworkManager {\n var urlSession: URLSession?\n \n func makeRequest() {\n guard let session = urlSession else {\n print("Erro: sessão não definida")\n return\n }\n // Trabalhando com session\n print("Requisição feita através de \\(session)")\n }\n}\n\n// Uso\nlet manager = NetworkManager()\nmanager.urlSession = URLSession.shared // Injeção de dependência\nmanager.makeRequest()\n\n3. Method Injection (Injeção via Método)
\nIdeal quando a dependência é necessária apenas para a execução de um método específico.
\n\nclass PaymentProcessor {\n func processPayment(amount: Double, using gateway: PaymentGatewayProtocol) -> Bool {\n // gateway é usado apenas aqui\n return gateway.charge(amount: amount)\n }\n}\n\nprotocol PaymentGatewayProtocol {\n func charge(amount: Double) -> Bool\n}\n\nclass StripeGateway: PaymentGatewayProtocol {\n func charge(amount: Double) -> Bool {\n print("Pagamento \\(amount) via Stripe")\n return true\n }\n}\n\n// Uso\nlet processor = PaymentProcessor()\nlet stripe = StripeGateway()\nlet result = processor.processPayment(amount: 99.99, using: stripe)\n\nPor que usar Injeção de Dependência em projetos iOS?
\n\nMuitos desenvolvedores Swift iniciantes ignoram a DI, considerando-a uma complexidade desnecessária. No entanto, na prática, as vantagens se tornam evidentes rapidamente:
\n\n- \n
- Simplificação de Testes (Testes Unitários): Você pode facilmente substituir serviços reais por