在iOS开发中,MVC架构形式下,操控器会过于臃肿,所以目前比较盛行的是MVVM架构形式。下面简略介绍一下iOS中MVVM的实践落地。

一、iOS的MVVM

下图是MVVM-C规划形式的结构图,其间的C指的不是操控器,而是作为展现或许封闭操控器的Coordinate(和谐器)。在实践开发中,咱们一般在Controller中完结展现或许封闭操控器的使命,所以这儿咱们不关注和谐器。

MVVM架构设计在iOS中的实践

1. 责任区分

比较MVC来说,新增了一个VM, 下面是各个模块的责任:

VMVMVM之间的桥梁, 供给一系列特点用于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 的一种,咱们能够将值经过它来发送,这些值会被发给观察者,最终订阅者收到回调。
  • BehaviorSubjectReplaySubject PublishSubject 类似,不过咱们能够在没有任何观察者连接上它时就进行值的发送,有新的观察者时,会接纳到之前发送过的暂存在 “重放”缓冲区上的值。
  • Disposable DisposeBag 分别用来操控一个或多个订阅的生命周期。当一个Disposable 被毁掉或许手动丢掉时,订阅行为就将完毕,别的该订阅的一切的可观察量组成部分也将被开释。

3. RxSwift 中的部分变形函数

  • Map:映射
  • Filter:过滤
  • concat:将两个A、B两个Observable“串行”起来,在A发送onComplete前只会接受A的音讯,A发送onComplete后才会接纳B的音讯。
  • Merge: 兼并多个可观察序列,当其间一个宣布音讯时,会收到订阅回调。
  • taketake(whiletake(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…