在前面的文章iOS常见架构中介绍了MVVM, 针对其中的核心点 - 数据绑定(Data Binding)并没有具体说明,今天来聊一聊如何用Swift 语言如何实现数据绑定。
![](https://img.haomeiwen.com/i1411204/1d6579767fee1605.png)
数据绑定作为View 和 ViewModel之间的桥梁,无论绑定方向是双向还是单向,都是为了让两个数据层以完全透明的方式联通。
遗憾的事,iOS 原生开发工具集并不支持数据绑定(Android开发者就幸福多了),开发者只能使用第三方框架或自己重新来实现。我们来看看当前一些主流的思路。
�委托
如果不想学习和引进新的框架,可以使用iOS SDK常用的 委托模式。
经验丰富的iOS开发者都知道委托需要手动设置,数据绑定不仅失去了透明的特性,模式也去进于MVP。
使用代理需要ViewModel持有代理的引用,代理的实现者是View(MVVM中Controller也属于View),这样ViewModel可以更新View, 而不依赖于View。
代码样例:
class ViewController: UIViewController, ViewModelDelegate {
@IBOutlet private weak var userLabel: UILabel?
private let viewModel: ViewModel
init(viewModel: ViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
viewModel.delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func userNameDidChange(text: String) {
userLabel?.text = text
}
}
protocol ViewModelDelegate: class {
func userNameDidChange(text: String)
}
class ViewModel {
init() {
userName = "王大路"
}
private var userName: String {
didSet {
delegate?.userNameDidChange(text: userName)
}
}
weak var delegate: ViewModelDelegate? {
didSet {
delegate?.userNameDidChange(text: userName)
}
}
}
闭包
闭包的策略类似于委托代理,主要是在ViewModel内定义闭包作为属性,通过闭包来更新View,在使用闭包时注意避免出现循环引用。
关于如何避免循环引用可以参看文章 Swift闭包和函数
。
代码样例:
class ViewController: UIViewController {
@IBOutlet private weak var userLabel: UILabel?
private let viewModel: ViewModel
init(viewModel: ViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
viewModel.userNameDidChange = { [weak self] (text: String) in
self?.userNameDidChange(text: text)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func userNameDidChange(text: String) {
userLabel?.text = text
}
}
class ViewModel {
var userNameDidChange: ((String) -> Void)? {
didSet {
userNameDidChange?(userName)
}
}
private var userName: String {
didSet {
userNameDidChange?(userName)
}
}
init() {
userName = "李小璐"
}
}
RxSwift (or ReactiveCocoa)
RxSwift 是 ReactiveX 家族中的Swift版本,其和 RxJava, RxJavascript, and 框架都是类似的,掌握了一个,其余的会容易上手。
![](https://img.haomeiwen.com/i1411204/6684856a08db861b.png)
利用这些框架可以轻松实现响应式函数编程 。
代码样例
class ViewController: UIViewController {
@IBOutlet private weak var userLabel: UILabel!
private let viewModel: ViewModel
private let disposeBag: DisposeBag
private func bindToViewModel() {
viewModel.myProperty
.drive(userLabel.rx.text)
.disposed(by: disposeBag)
}
}
关于如何使用RxSwift请参看官方文档,这里就不做介绍了。
如果不喜欢 RxSwift 框架,可以尝试 ReactiveCocoa。如果不习惯响应式函数编程,只能多花几小时熟悉,它和传统的编程方式区别很大。
自实现简单binding样例
更多
获取更多内容请关注微信公众号豆志昂扬:
- 直接添加公众号豆志昂扬;
- 微信扫描下图二维码;
![](https://img.haomeiwen.com/i1411204/028e2a1c709bbbac.jpg)
网友评论