1. MVVM架构简介
对于MVVM
架构,大家一定都已不再陌生,网上的资料随意一搜遍地都是,这里就不再过多的赘述,简单说一下MVVM
架构结合RxSwift
的使用,以及各自的分工,请看下面这张图:
注意:MVVM
架构并不是一定得结合函数响应式编程RxSwift
或者RAC
等,只是他们的结合会使得代码更加的简洁,消息的传递更加简单化。
Model
提供数据支持,在里面定义需要的属性等;
ViewModel
主要职责就是对数据进行转换处理,ViewModel
中设计Input结构体
和Output结构体
的作用主要是使得事件的流向更加的清晰;Input
所扮演的角色,主要是接收View
所传递过来的事件(点击、输入、滚动等),ViewModel
内部通过transform
函数转换,返回OutPut
,Output
的作用主要是保存处理后的结果,用于将来绑定到UI
,从而实现了View
与ViewModel
层完全的解耦;
View
主要作用就是视图的布局、动画、跳转等,将来会把所需的事件传递给ViewModel
的Input
中,通过ViewModel
的数据转换,把ViewModel
中的Output
绑定到对应的UI
控件上;在MVVM
中Controller
也会归属到View
中,职责类似;
2. 关注功能实战
需求:页面内有一按钮,有“关注”和“取消关注”两种状态,进入页面通过网络请求获取初始状态,然后通过点击,发起请求,切换不同的状态,具体实现如下:
Model层
声明按钮的初始状态属性,isAttention
用于存储是否关注的状态;
class AttentionModel { var isAttention = false }
View层
主要是创建控件、以及ViewModel
实例,并把按钮的点击事件传递到ViewModel
的Input
中,ViewModel
内部通过transform
函数,对input
中的事件进行处理,再把ViewModel
中的Output
和按钮的状态attentionButton.rx.isSelected
绑定在一起;
private func bindToViewModel() { let output = viewModel.transform(input: AttentionViewModel.Input(attention: attentionButton.rx.tap)) output.attentionStatus.bind(to: attentionButton.rx.isSelected).disposed(by: disposeBag) }
ViewModel层
Input:保存传递过来的按钮点击事件;
Output:绑定按钮状态数据到View
层;
transform:ViewModel
中attention
作用主要是用于存储当前的按钮状态;transform
函数内部initAction
主要是用于请求更新按钮初始时的状态,attentionAction
主要是当按钮点击的时候发起请求,待收到响应后,更新响应结果,通过merge
两者的状态,利用Output
的attentionStatus
回调给外界进行绑定;
struct AttentionViewModel { //false代表未关注 true已关注 private var attention = BehaviorRelay<Bool>(value: false) struct Input { let attention: ControlEvent<Void> } struct Output { let attentionStatus: Observable<Bool> } func transform(input: Input) -> Output { let initAction = requestInit()//请求初始数据 let attentionAction = input.attention.flatMap({ request(!attention.value)} ).observe(on: MainScheduler.instance).share(replay: 1) //关注、取消关注点击 //合并结果-把按钮点击或者请求初始数据的时候都去更新关注按钮状态 let attentionStatus = Observable.of(attentionAction, initAction).merge() return Output(attentionStatus: attentionStatus) } private func request(_ isAttention: Bool) -> Observable<Bool> { return Observable<Bool>.create { (observer) -> Disposable in Logger("发起更新状态请求\nLoading...") DispatchQueue.global().asyncAfter(deadline: .now() + 2, execute: { Logger("响应更新状态结果...isAttention = \(isAttention)") observer.onNext(isAttention)//是否关注 self.attention.accept(isAttention)// 关注或取消关注成功、存储状态 }) return Disposables.create() }.subscribe(on: ConcurrentDispatchQueueScheduler(qos: .userInteractive)) } private func requestInit() -> Observable<Bool> { return Observable<Bool>.create { (observer) -> Disposable in Logger("正在请求初始状态\nLoading...") DispatchQueue.global().asyncAfter(deadline: .now() + 1, execute: { let model = AttentionModel()//模拟将请求结果转换为Model... model.isAttention = true //假设默认状态为已关注 Logger("初始状态响应结果...isAttention = \(model.isAttention) \n") //Event处理... observer.onNext(model.isAttention)//用于通知View去更新关注状态 attention.accept(model.isAttention)//存储关注的状态 }) return Disposables.create() }.subscribe(on: ConcurrentDispatchQueueScheduler(qos: .userInteractive)) } }
运行结果:
Log - 正在请求初始状态 Loading... Log - 初始状态响应结果...isAttention = true Log - 发起更新状态请求 Loading... Log - 响应更新状态结果...isAttention = false
藏划线