以编程方式推送视图控制器时,可以轻松地通过init方法进行一些依赖项注入:
let dummyVC = DummyVC(dummyManager: DummyManager())
self.pushViewController(dummyVC, animated: true)
使用目标控制器:
class DummyVC: UIViewController {
private let dummyManager: DummyManager
init(dummyManager: DummyManager) {
self.dummyManager = dummyManager
super.init(nibName: nil, bundle: nil)
}
}
前面的代码很好,因为它正确封装了属性并清楚地显示了对外部API的依赖性。
在使用Storyboard时,我们无法选择要调用的init方法(正在调用自定义init方法)。
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let dummyVC = mainStoryboard.instantiateViewControllerWithIdentifier("DummyVC") as! DummyVC
dummyVC.dummyManager = DummyManager() // ERROR: would require dummyManager to have public scope
有什么方法可以在保持属性私有和常量(let)的同时以相同的方式注入依赖项?
答案 0 :(得分:2)
情节提要中的视图控制器始终使用
进行初始化init?(coder aDecoder: NSCoder)
没有办法解决。
另一种选择是……
class DummyVC: UIViewController {
private var dummyManager: DummyManager!
func configure(dummyManager: DummyManager) {
self.dummyManager = dummyManager
}
}
然后……
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let dummyVC = mainStoryboard.instantiateViewControllerWithIdentifier("DummyVC") as! DummyVC
dummyVC.configure(dummyManager: DummyManager())
或
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.destination {
case let dummyVC as DummyVC:
dummyVC.configure(dummyManager: DummyManager())
default:
break
}
}
虽然不完美(使用let
而不是var
),该属性为private
和一个隐式解包的可选意味着必须对其进行设置(否则应用将在使用时崩溃),并且那只能在包含类内部发生。
我在所有应用程序中都采用了此方法,并发现这是确保设置所有属性的一种不错的方法。只需记住在将属性添加到类时更新configure
函数即可。