生成你的依赖注入。旨在安全。
AnnotationInject | |
---|---|
🗽 | 让你从手动注册依赖中解放出来。 |
⚡ | 花更少的时间配置,更多的时间编码! |
🛡 | 不再有运行时崩溃,因为依赖不是最新的。一切都在编译时检查。 |
👐 | 基于你喜欢的开源工具,如 Sourcery 和 Swinject。 |
📖 | 100% 开源,基于 MIT 许可证 |
特定版本的文档可能略有不同。如果您遇到问题,请先查看版本文档(通过在 Github 分支/标签中选择版本)。
使用依赖注入库(例如 Swinject),你需要记住注册你的依赖
container.register(CoffeeMaker.self) { r in
return CoffeeMaker(heater: r.resolve()!) // Trouble ahead, not sure Heater is in fact registered!
}
/// later in your code
let coffeeMaker = container.resolve(CoffeeMaker.self) // crash, missing Heater dependency!
运行这段代码,我们会在运行时得到一个崩溃:我们没有注册任何 heater
,导致 CoffeeMaker 解析器崩溃。
注解将生成你的依赖,并确保一切都在编译时解析。
/// sourcery: inject
class CoffeeMaker {
init(heater: Heater) {
}
}
这次我们会得到一个编译时错误,因为我们忘记声明 Heater
依赖。万岁!
/// sourcery: inject
class CoffeeMaker {
init(heater: Heater) { }
}
/// sourcery: inject
class Heater {
init() { }
}
请参阅 安装 以了解更多详情。
如果并非所有依赖都可以解析,构建阶段将失败,阻止你的代码成功编译。
let resolver = Assembler([AnnotationAssembly()]).resolver
// `registeredService` is generated code. It is completely safe at compile time.
let coffeeMaker = resolver.registeredService() as CoffeeMaker
let heater = resolver.registeredService() as Heater
注意:AnnotationInject 依赖/依赖于 Sourcery 进行注解声明,以及 Swinject 作为依赖注入器。
dependencies: [
.package(url: "https://github.com/pjechris/AnnotationInject.git", from: "0.6.0")
]
然后将 Build phases
添加到你的项目中
swift run annotationinject-cli --sources <path to your sources> --output <path to output generated code> (--args imports=<MyLib1> -args imports=<MyLib2>>)
在 Xcode 中添加 AnnotationInject 作为依赖,然后将此 Build phase
添加到你的项目中
SPM_CHECKOUT_DIR=${BUILD_DIR%Build/*}SourcePackages/checkouts/AnnotationInject
cd $SPM_CHECKOUT_DIR
/usr/bin/xcrun --sdk macosx swift run annotationinject-cli ...
将 pod AnnotationInject
添加到你的 Podfile
,并将新的 Build phases
添加到你的项目中
"$(PODS_ROOT)"/AnnotationInject/Scripts/annotationinject --sources <path to your sources> --output <path to output generated code> (--args imports=<MyLib1> -args imports=<MyLib2>>)
注意:你可以将所有
sourcery
命令行选项传递给annotationinject
脚本。
sourcery --templates <path to copied templates> --sources <path to your sources> --output <path to output generated code> (--args imports=<MyLib1> -args imports=<MyLib2>>)
将类注册到依赖容器中。
/// sourcery: inject
class CoffeeMaker { }
container.register(CoffeeMaker.self) {
return CoffeeMaker()
}
extension SafeDependencyResolver {
func registeredService() -> CoffeeMaker {
return resolve(CoffeeMaker.self)!
}
}
/// sourcery:inject: scope = "weak", type = "Maker", name = "Arabica"
class CoffeeMaker: Maker { }
注册一个特定的 init 用于注入。如果未提供注解,则使用第一个找到的 init。
注意:类仍然需要用
inject
注解。
// sourcery: inject
class CoffeeMaker {
init(heater: Heater) { }
// sourcery: inject
convenience init() {
self.init(heater: CoffeHeater())
}
}
container.register(CoffeeMaker.self) {
return CoffeeMaker()
}
extension SafeDependencyResolver {
func registeredService() -> CoffeeMaker {
return resolve(CoffeeMaker.self)!
}
}
在 init 之后注入一个属性。属性需要标记为 Optional (?
或 !
)。
注意:类仍然需要用
inject
注解。
// sourcery: inject
class CoffeeMaker {
/// sourcery: inject
var heater: Heater!
init() { }
}
container.register(CoffeeMaker.self) {
return CoffeeMaker()
}
.initCompleted { service, resolver in
service.heater = resolver.registeredService()
}
使用自定义函数来注册你的依赖。这与手动实现 container.register
并在保持安全性的同时相同。请注意,提供的方法必须被调用 instantiate
。
注意:如果你正在提供第三方库(例如来自 Cocoapods),你将需要使用
args.imports MyLib,MyLib2,...
命令行参数将这些导入传递给 AnnotationInject。
class CoffeeMaker {
init(heater: Heater) { }
}
// sourcery: provider
class AppProvider {
static func instantiate(resolver: SafeDependencyResolver) -> CoffeeMaker {
return CoffeeMaker(heater: CoffeHeater())
}
}
container.register(CoffeeMaker, factory: AppProvider.instantiate(resolver:))
extension SafeDependencyResolver {
func registeredService() -> CoffeeMaker {
return resolve(CoffeeMaker.self)!
}
}
声明一个参数作为参数来定义到解析器方法中。适用于 init 和 provider 方法。
生成的代码由于缺少导入而无法编译
设置 --args imports=<MyLib1> -args imports=<MyLib2>>
以便生成的代码包含第三方库。
Foundation 类型 (URLSession, NSNotificationCenter, ...) 在生成的代码中为空 (.self)
Sourcery 尚无法找到这些类型。因此,它们被视为不存在。解决方法:在 Provider 内部定义周围的类型,并为其提供 Foundation 类型。
构建阶段失败,但没有报告错误
这可能是由于 Sourcery 与 Xcode 11.4 存在一些不兼容性。解决方法:使用 Homebrew 安装 Sourcery,然后添加到构建步骤 SOURCERY_BINPATH=sourcery
作为环境变量。
Pods/Sourcery/bin/Sourcery.app/Contents/MacOS/Sourcery: No such file or directory
你可能正在使用 Sourcery 作为 Cocoapods 依赖项,但不幸的是,这并非总是有效。解决方法:使用 Homebrew 安装 Sourcery,然后添加到构建步骤 SOURCERY_BINPATH=sourcery
作为环境变量。
本项目根据 MIT 许可证发布。请参阅 LICENSE 文件以了解详情。