Swift(iOS/macOS)的依赖注入容器:Swinject

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swinject — Swift(iOS/macOS)的依赖注入容器



依赖注入(DI)是 SOLID 原则中的关键原则之一,它允许创建松耦合、可测试且可扩展的代码。在 Swift 的 iOS 和 macOS 开发世界中,实现 DI 的最流行库之一是 Swinject。这是一个轻量级但功能强大的依赖注入容器,简化了对象及其生命周期的管理。



在本文中,我们将详细探讨 Swinject 的工作原理、如何安装以及在真实项目中使用它。



什么是依赖注入以及为什么需要容器?

依赖注入是一种技术,对象从外部获取其依赖项,而不是自己创建它们。这提高了灵活性并简化了测试。DI 容器(例如 Swinject)自动化了对象创建和绑定的过程,使开发者免于编写样板代码。



安装 Swinject

Swinject 可以通过 Swift Package Manager、CocoaPods 或 Carthage 安装。我们来看最现代的方式——SPM:



// 在 Xcode 中:File → Swift Packages → Add Package Dependency// URL:https://github.com/Swinject/Swinject.git// 版本:2.8.0 及以上


或者将其添加到 Package.swift:

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


Swinject 的主要组件

  • Container — 注册和解析依赖项的主要对象。
  • Service — 我们想要注入的类型(协议或类)。
  • Registration — 将抽象(协议)与具体实现绑定的过程。
  • Scope — 管理对象的生命周期(瞬态、单例等)。


基本使用示例

假设我们有一个协议 NetworkServiceProtocol 及其实现 NetworkService:



import Swinject

protocol NetworkServiceProtocol { func fetchData() -> String}

class NetworkService: NetworkServiceProtocol { func fetchData() -> String { return "数据已获取" }}

// 创建容器let container = Container()

// 注册依赖项container.register(NetworkServiceProtocol.self) { _ in NetworkService() }

// 解析(获取)实例let service = container.resolve(NetworkServiceProtocol.self)!print(service.fetchData()) // "数据已获取"


在 ViewController(iOS)中注入依赖项

最常见的是,Swinject 用于将服务注入到控制器中。我们来看一个带有视图模型的示例:



import Swinject

// 视图模型的协议和实现protocol UserViewModelProtocol { func getUsers() -> [String]}

class UserViewModel: UserViewModelProtocol { private let networkService: NetworkServiceProtocol init(networkService: NetworkServiceProtocol) { self.networkService = networkService } func getUsers() -> [String] { // 使用 networkService 加载数据 return ["Alice", "Bob"] }}

// 在容器中注册container.register(UserViewModelProtocol.self) { resolver in let network = resolver.resolve(NetworkServiceProtocol.self)! return UserViewModel(networkService: network)}

// 在控制器中使用class UsersViewController: UIViewController { var viewModel: UserViewModelProtocol? override func viewDidLoad() { super.viewDidLoad() viewModel = container.resolve(UserViewModelProtocol.self) print(viewModel?.getUsers() ?? []) }}


对象的生命周期(Scopes)

Swinject 支持多种作用域:

推荐