Swoin
Swoin 是一个 Swift 依赖注入框架,受 Koin 启发
开始使用
将框架添加到项目中,例如使用 Cocoapods
pod 'Swoin'
将依赖项添加到某些模块中,然后传递给 startSwoin
生成器以启动全局 Swoin 实例
class SwoinCreator: SwoinComponent {
//...
func start() {
let appModule = Module {
single { CustomNavigationController() }
.bind(UINavigationController.self)
weak(named: "TestSubject") { PublishSubject<Void>() }
.bind(Observable<Void>.self) { $0.asObservable() }
.bind(AnyObserver<Void>.self) { $0.asObserver() }
weak { HomeViewModel(input: get(), output: get()) }
weak { HomeViewController(viewModel: get(), view: get()) }
weak { HomeView() }
}
let thingModule = Module {
factory { Thing() }
single { ThingFetcher(thing: get()) }
.bind(IntFetcher.self)
.bind(StringFetcher.self)
}
startSwoin {
appModule
thingModule
logger(Swoin.printLogger)
}
}
}
使用 @Inject 懒加载字段
@Inject private var navigationController: CustomNavigationController
或使用 get()
强加载
let controller: TipsViewController = get()
rootViewController.pushViewController(controller, animated: true)
请注意,get()
只能用于实现 SwoinComponent
的调用类
// This is fine:
struct Cowboy: SwoinComponent {
var horse: Horse = get()
}
// This will not compile, "Cannot find 'get' in scope":
struct Horse {
let saddle: Saddle = get()
}
支持命名依赖项
@Inject(named: "TestSubject") private var testObservable: Observable<Void>
let observer: PublishSubject = get(named: "TestSubject")
缓存类型
支持三种缓存策略
- 只要模块保持加载状态,就创建一次
single
依赖项,即单例 - 在解析任何时间都重新创建
factory
依赖项 - 如果没有其他强引用到该类型的任何先前创建的实例,则重新创建
weak
依赖项
绑定其他类型
您可以使用.bind
将多个类型绑定到依赖注册,并传递一个可选的闭包以将其转换为该类型。
weak(named: "TestSubject") { PublishSubject<Void>() }
.bind(Observable<Void>.self) { $0.asObservable() }
.bind(AnyObserver<Void>.self) { $0.asObserver() }
绑定的类型与其所绑定依赖项具有相同的名称和缓存策略。
如果原始类型实现了协议,则闭包是可选的,因为默认是{ $0 as! NewType }
,但显然如果在运行时强制转换不可行,这会导致程序崩溃。
初始化之后的代码运行
您可以使用.then
在依赖项初始化后执行一个动作。
private class CircularDependencyOne {
let dependencyTwo: CircularDependencyTwo
init(_ dependencyTwo: CircularDependencyTwo) {
self.dependencyTwo = dependencyTwo
}
}
private class CircularDependencyTwo {
var dependencyOne: CircularDependencyOne?
}
let testModule = Module {
single { CircularDependencyOne(get()) }
.then {
$0.dependencyTwo.dependencyOne = $0
}
single { CircularDependencyTwo() }
}