Dip-UI 是 Dip 的扩展,它为使用故事板和 nib 文件的的应用程序提供依赖注入的支持。
您可以使用您喜欢的依赖管理器安装 Dip-UI
pod "Dip-UI"
要为 Swift 2.3 构建,请将以下代码添加到 Podfile 的底部
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '2.3'
end
end
end
您需要至少 1.1.0.rc.2 版本的 CocoaPods。
要为 Swift 2.3 构建,请使用 --toolchain com.apple.dt.toolchain.Swift_2_3
选项运行 Carthage。
Dip-UI 提供了解决由故事板创建的视图控制器(或任何其他 NSObject
)依赖关系的统一简单模式。
假设您想在 MyViewController
类中使用 Dip 注入依赖,该类定义如下
class MyViewController: UIViewController {
var logger: Logger?
var tracker: Tracker?
var router: Router?
var presenter: MyViewControllerPresenter?
var service: MyViewControllerService?
/*...*/
}
注意 1:虽然构造器注入是注入依赖的首选方式,但在此情况下我们无法使用它 - 我们无法让故事板使用自定义构造器。我们可以通过继承 UI:NSStoryboard 和方法适配来实现这一点,但您不会期望在 Swift 框架中看到这样的东西。
注意 2:在这里使用非可选隐式解包来表示这些依赖对该类是必需的。您不必遵循此模式,可以选择如果您喜欢,则可以使用纯可选值。
在从故事板实例化此视图控制器时,注入依赖的步骤如下
DependencyContainer
中注册依赖项,以及 MyViewController
import Dip
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
let container = DependencyContainer { container in
container.register(.Singleton) { LoggerImp() as Logger }
container.register(.Singleton) { TrackerImp() as Tracker }
container.register(.Singleton) { RouterImp() as Router }
container.register { MyViewControllerPresenterImp() as MyViewControllerPresenter }
container.register { MyViewControllerServiceImp() as MyViewControllerService }
container.register(tag: "myVC") { MyViewController() }
.resolvingProperties { container, controller in
container.logger = try container.resolve() as Logger
container.tracker = try container.resolve() as Tracker
container.router = try container.resolve() as Router
container.presenter = try container.resolve() as MyViewControllerPresenter
container.service = try container.resolve() as MyViewControllerService
}
DependencyContainer.uiContainers = [container]
}
}
注意:所有依赖项均注册为抽象(协议)的实现。将
MyViewController
注册为具体类型。但是,您也可以使您的视图控制器符合某些协议,并将它们注册为这些协议的实现。
DependencyContainer
类的静态 uiContainers
属性来完成此操作DependencyContainer.uiContainers = [container]
StoryboardInstantiatable
协议extension MyViewController: StoryboardInstantiatable { }
提示:在组合根中这样做以避免将视图控制器代码与 Dip 框架耦合。
注意:记住,如果
DependencyContainer
没有找到标记定义,它将回退到未标记的定义,因此您可以在没有标记的情况下注册您的视图控制器,但仍需要在一故事板中设置它。在这种情况下,您可以使用Nil
属性类型而不是String
。
现在,当视图控制器从故事板加载时,Dip-UI 将拦截 dipTag
属性的设置器,并要求 DependencyContainer.uiContainer
解析其依赖项。
StoryboardInstantiatable
协议定义了一个名为 didInstantiateFromStoryboard(_:tag:)
的单个方法,并提供了默认实现。在大多数情况下,您不需要重写它。但是,如果您将视图控制器注册为某些协议的实现而不是具体类型,或者想要执行一些前置/后置操作,您需要像这样重写它
container.register { MyViewController() as MyScene }
extension MyViewController: StoryboardInstantiatable {
func didInstantiateFromStoryboard(container: DependencyContainer, tag: DependencyContainer.Tag?) throws {
try container.resolveDependenciesOf(self as MyScene, tag: tag)
}
}
Dip-UI 在 MIT 许可证 下可用。有关更多信息,请参阅 LICENSE
文件。