Container de Injeção de Dependência para Swift (iOS/macOS): Swinject

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Swinject — Container de Injeção de Dependência para Swift (iOS/macOS)



Injeção de Dependência (DI) é um dos princípios chave do SOLID, permitindo criar código fracamente acoplado, testável e escalável. No mundo Swift para desenvolvimento iOS e macOS, uma das bibliotecas mais populares que implementam DI é o Swinject. É um container de injeção de dependência leve, mas poderoso, que simplifica o gerenciamento de objetos e seu ciclo de vida.



Neste artigo, vamos detalhar como o Swinject funciona, como instalá-lo e usá-lo em projetos reais.



O que é Injeção de Dependência e para que serve um container?

Injeção de dependência é uma técnica na qual um objeto recebe suas dependências externamente, em vez de criá-las por si só. Isso aumenta a flexibilidade e simplifica os testes. Um container DI (por exemplo, Swinject) automatiza o processo de criação e vinculação de objetos, poupando o desenvolvedor de escrever código boilerplate.



Instalação do Swinject

O Swinject pode ser instalado usando Swift Package Manager, CocoaPods ou Carthage. Vamos considerar o método mais moderno — SPM:



// No Xcode: File → Swift Packages → Add Package Dependency// URL: https://github.com/Swinject/Swinject.git// Versão: a partir de 2.8.0


Ou adicione no Package.swift:

dependencies: [    .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0")]


Componentes principais do Swinject

  • Container — o objeto principal onde as dependências são registradas e resolvidas.
  • Service — o tipo (protocolo ou classe) que queremos injetar.
  • Registration — o processo de vincular uma abstração (protocolo) a uma implementação concreta.
  • Scope — gerencia o ciclo de vida do objeto (transiente, singleton, etc.).


Exemplo básico de uso

Suponha que temos um protocolo NetworkServiceProtocol e sua implementação NetworkService:



import Swinject

protocol NetworkServiceProtocol { func fetchData() -> String}

class NetworkService: NetworkServiceProtocol { func fetchData() -> String { return "Dados obtidos" }}

// Criamos o containerlet container = Container()

// Registramos a dependênciacontainer.register(NetworkServiceProtocol.self) { _ in NetworkService() }

// Resolvemos (obtemos) a instâncialet service = container.resolve(NetworkServiceProtocol.self)!print(service.fetchData()) // "Dados obtidos"


Injeção de dependências no ViewController (iOS)

Na maioria das vezes, o Swinject é usado para injetar serviços nos controladores. Vamos ver um exemplo com uma view-model:



import Swinject

// Protocolo e implementação da view-modelprotocol UserViewModelProtocol { func getUsers() -> [String]}

class UserViewModel: UserViewModelProtocol { private let networkService: NetworkServiceProtocol init(networkService: NetworkServiceProtocol) { self.networkService = networkService } func getUsers() -> [String] { // Usamos networkService para carregar return ["Alice", "Bob"] }}

// Registro no containercontainer.register(UserViewModelProtocol.self) { resolver in let network = resolver.resolve(NetworkServiceProtocol.self)! return UserViewModel(networkService: network)}

// Uso no controladorclass UsersViewController: UIViewController { var viewModel: UserViewModelProtocol? override func viewDidLoad() { super.viewDidLoad() viewModel = container.resolve(UserViewModelProtocol.self) print(viewModel?.getUsers() ?? []) }}


Ciclos de vida dos objetos (Scopes)

O Swinject suporta vários scopes:

  • .transient

Recommendations