在iOS开发中,MVC架构形式下,操控器会过于臃肿,所以目前比较盛行的是MVVM架构形式。下面简略介绍一下iOS中MVVM的实践落地。
一、iOS的MVVM
下图是MVVM-C
规划形式的结构图,其间的C
指的不是操控器,而是作为展现或许封闭操控器的Coordinate
(和谐器)。在实践开发中,咱们一般在Controller
中完结展现或许封闭操控器
的使命,所以这儿咱们不关注和谐器。
1. 责任区分
比较MVC
来说,新增了一个VM
, 下面是各个模块的责任:
VM:VM
是V
和M
之间的桥梁, 供给一系列特点用于View
的显示,特点包含将Model
变形转化为View
展现时应有的值。在iOS中一般还会担任网络请求及Model
更新。
VC:担任树立VM
中特点与View
的绑定联系;担任交互事件响应的详细逻辑;假如不树立图中和谐器时,一般还包括还包括页面的跳转逻辑。
V: 视图的详细创建和用户交互监听,模型中数据的呈现逻辑。
M:担任存储和办理应用程序所需的数据,以及履行相关的业务逻辑。它不应该与V
或许VM
或许操控器
产生耦合。
2. 响应式编程RxSwift
来做绑定
- 上述提到
VC
中担任树立绑定联系,咱们能够运用KVO
来完成,但在有需求数据变形转化时比较麻烦,不引荐;RxSwift
是专门用于响应式编程的一套框架,里边供给了许多变形相关的函数,能帮助更好的树立绑定联系。 - 运用
RxSwift
,能够根据需求来完成单向或许双向的绑定,当咱们娴熟RxSwift
的函数后,能提升咱们的代码质量和便捷性。
二、一个响应式编程比如
下面是运用RxSwift完成的简略绑定:
var modelObject: ModelObject!
var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
modelObject.valueObservable.map { possibleValue -> String in
if let value = possibleValue {
return "Selected value is: \(value)"
} else {
return "No value selected"
}
}.bind(to: self.textLabel.rx.text).disposed(by: disposeBag)
}
1. 为什么绑定很重要?
如上代码,比较于在许多当地设置 textLabel.text
的值,树立绑定后这个 textLabel
只会在最终被引证一次。响应式编程让咱们从目的地—也便是数据的订阅者开始,一路经过数据变形进行回溯,直到抵达原始的数据依赖 – 可观察量 (observable
)。经过这么做,数据管道的可观察量
,数据变形
以及订阅者
三者得以别离。
数据变形的部分是响应式编程所能带来的最大优势,但一起它也是学习曲线最为陡峭的部分。
2. RxSwift中的一些根本类型
-
Observable
是一个可观察量,咱们能够对它们进行变形,订阅,或许将它们绑定到UI 元素上去。 -
PublishSubject
是Observable
的一种,咱们能够将值经过它来发送,这些值会被发给观察者,最终订阅者收到回调。 -
BehaviorSubject
、ReplaySubject
和PublishSubject
类似,不过咱们能够在没有任何观察者连接上它时就进行值的发送,有新的观察者时,会接纳到之前发送过的暂存在 “重放”缓冲区上的值。 -
Disposable
和DisposeBag
分别用来操控一个或多个订阅的生命周期。当一个Disposable
被毁掉或许手动丢掉时,订阅行为就将完毕,别的该订阅的一切的可观察量组成部分也将被开释。
3. RxSwift 中的部分变形函数
-
Map
:映射 -
Filter
:过滤 -
concat
:将两个A、B两个Observable“串行”起来,在A发送onComplete
前只会接受A的音讯,A发送onComplete后才会接纳B的音讯。 -
Merge
: 兼并多个可观察序列,当其间一个宣布音讯时,会收到订阅回调。 -
take
与take(while
、take(until
等:操控订阅次数或根据触发条件订阅。 -
flatMapLatest
:只保存flatMapLatest
回来的最新一个Observable
的订阅(flatMapLatest
函数回来的是一个Observable
)。
更详细的内容能够在RxSwift的网站检查:
三、一个双向绑定的比如
大多情况下,咱们只需求单向绑定;但有时候可能会需求双向绑定,下面是一个双向绑定的示例: 登录页输入框要与VM的数据双向绑定。
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var label: UILabel!
var userVM = UserViewModel()
let disposeBag = DisposeBag()
override func viewDidLoad() {
//将用户名与textField做双向绑定
userVM.username.asObservable().bind(to: textField.rx.text).disposed(by: disposeBag)
textField.rx.text.orEmpty.bind(to: userVM.username).disposed(by: disposeBag)
//将用户信息绑定到label上
userVM.userinfo.bind(to: label.rx.text).disposed(by: disposeBag)
}
}
// 咱们能够将双向绑定定义一个为一个操作符(官方demo中有这个文件,可复制)
// 上述中双向绑定的代码能够简化为:
//将用户名与textField做双向绑定
_ = self.textField.rx.textInput <-> self.userVM.username
假如感兴趣的话,能够在RxSwift
中的github
上的样板工程:
github.com/ReactiveX/R…