前言 如果你想设计一个 MVVM 架构的新项目,那么如何实现数据绑定,是一个需要关心的问题。
当然,如果你非要使用 Delegate 或者 Notification 去做的话,其实也没问题,但我想,这应该都不算优雅的方式。
数据绑定的成熟方案,有比如 RXSwift,KVO 等等,感兴趣的朋友可以去搜索一下,但是,假如你在使用 Swift,事实上有一个现成的被遗忘的方案,那就是 Swift 中无所不能的闭包 。
实现 说再多也没用,直接上代码,实现一个 Box
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 final class Box<T> { // 声明一个别名 typealias Listener = (T) -> Void var listener: Listener? var value: T var wrappedValue: T { set { value = newValue listener?(value) } get { return value } } init(_ value: T){ self.value = value } func bind(listener: Listener?) { self.listener = listener listener?(value) } }
大功告成
如何使用 假如我们的 ViewController 有一个 UILabel 是这样的
1 2 3 4 5 6 7 lazy var label:UILabel = { let label = UILabel() label.textColor = .red label.textAlignment = .center label.frame = view.bounds return label }()
我们需要在加载一个延时任务后,去更新它,在 MVVM 的架构下,我们可以这么做:
先简单实现一个 ViewModel,大概是这样
1 2 3 4 5 6 7 8 9 10 class ViewModel { var texts: Box<String> = Box("") func fetchData() { DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 2) { DispatchQueue.main.async { self.texts.wrappedValue = "lufei" } } } }
然后在 ViewController 中做一下数据绑定
1 2 3 4 viewModel.texts.bind { [weak self](value) in guard let self = self else {return} self.label.text = value }
最后在你觉得合适的时机拉取数据
然后整段代码就变得格外优雅起来了,心情也会变成一样的~