在Swift中使用Storyboard和Segue時的依賴注入
Demo下載
我們都知道在使用Storyboard時恨豁,實(shí)現(xiàn)依賴注入總是有點(diǎn)不優(yōu)雅,讓我們先來看看在Objective-C時如何使用:
Objective-C
//In RJDemoViewController.m
- (void)setDependenciesViewModel:(RJDemoViewModel *)viewModel delegate:(id <RJDemoViewControllerDelegate>)delegate
{
self.viewModel = viewModel;
self.delegate = delegate;
}
- (void)assertDependencies
{
// 依賴的對象
NSParameterAssert(self.viewModel &&self.delegate);
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self assertDependencies];
}
然后就可以在prepareForSegue
中設(shè)置依賴:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:showDemoViewController]) {
RJDemoViewController *viewController = segue.destinationViewController;
NSParameterAssert([viewController isKindOfClass:[RJDemoViewController class]]);
[viewController setDependenciesViewModel:[self viewModelForSelectedThing] delegate:self];
}
}
至此宪摧,當(dāng)所有的依賴一旦沒有被注入,軟件就會立刻奔潰霞幅,錯誤定位也變得十分地方便知市。
然后在Swift
中有沒有存在更Swift的方式來實(shí)現(xiàn)依賴注入?yún)龋?/p>
Swift
首先定義一個協(xié)議(Protocol):
protocol Injectable {
associatedtype InjectObject
func inject(_: InjectObject)
func assertDependencies()
}
注意func inject(_: InjectObject)
由于ViewController依賴的對象有可能是Number,String
等等各種類型活孩,為了可讀性物遇,所以忽略了inject
方法的參數(shù)名,由遵循該協(xié)議的ViewController
去自由定義:
class RJDemoViewController: UIViewController, Injectable {
@IBOutlet weak private var mainLabel: UILabel!
private var mainText: String!
override func viewDidLoad() {
super.viewDidLoad()
//由于mainText是String!類型询兴,若沒賦值乃沙,這里就會Crash
assertDependencies()
// 大膽地使用mainText
mainLabel.text = mainText
}
//注: 這里參數(shù)名定義為text,提高了可讀性
func inject(text: String) {
mainText = text
}
func assertDependencies() {
assert(mainText != nil)
}
}
至此诗舰,在prepareForSegue
中警儒,便可實(shí)現(xiàn)注入
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDemoViewController" {
let vc = segue.destinationViewController as! RJDemoViewController
vc.inject("myMainText")
}
}