iOS MVVM 与 RxSwift

本文介绍了iOS开发中如何使用MVVM架构和RxSwift进行响应式编程,以解决ViewController过于臃肿的问题。MVVM将UI布局与逻辑处理分离,而RxSwift则简化了组件间的通信。通过PublishSubject、BehaviorSubject和ReplaySubject等类型,实现值的观察与更改。同时,文章详细解释了map、flatMap、scan和combineLatest等操作符的用法,并提供了一个登录页面的实战示例,帮助开发者理解MVVM和RxSwift的结合应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MVVM

Model:数据模型
View:UI展示
ViewModel:逻辑处理
工程目录图
架构解决问题:

  • viewcontroller太重,ui布局与逻辑处理没有很好的区分开来。所以一个viewcontroller的文件,很容易就写到几千行。
  • 将逻辑处理内容区分开来,专门放到一个类里去处理,就出现了viewmodel,连接view 和 model。

model:

class UserModel: NSObject {
    var userName:String = ""
    var password:String = ""
}

viewModel:

var userModel:PublishSubject<UserModel?>

override init() {
    userModel = PublishSubject()
}

func loginAction(userName:String, password:String)

view:

var userViewModel = UserViewModel()

@IBOutlet weak var userNameTextField: UITextField!

@IBOutlet weak var passwordTextField: UITextField!

@IBOutlet weak var loginButton: UIButton!

整体项目功能:
1、登录页面 (view)
2、调用登录 (viewmodel)
3、返回数据 (model)
4、数据赋值(viewmodel)
5、页面变化(view)


RxSwift

响应式编程,简化层级架构之间的通信,不用依靠delegate、notification,代码结构更加清晰。

察值:
view:观察viewModel中的userModel是否发生变化。如果发生变化,根据userModel的内容,判定是否登录成功

self.userViewModel.userModel.subscribeNext({ UserModel in
    if (UserModel == nil) {
        print("登录失败")
    }
    else {
        print("登录成功")
    }
}).addDisposableTo(disposeBag)

viewmodel:注意持有的model的类型(见最上viewmodel内容图)

PublishSubject:只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。

BehaviorSubject:当观察者订阅 BehaviorSubject 时,它开始发射原始 Observable 最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始Observable的数据。

Variable:封装了 BehaviorSubject 。使用 variable 的好处是 variable 将不会显式的发送 Error 或者 Completed 。在 deallocated 的时候, Variable 会自动的发送 complete 事件。

ReplaySubject:会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。当一个新的 observer 订阅了一个 ReplaySubject 之后,他将会收到当前缓存在 buffer 中的数据和这之后产生的新数据

改值

判断输入框的输入长度是否达到指定长度

let userNameValid = userNameTextField.rx_text.map{
    $0.characters.count >= minimalUsernameLength
    }.shareReplay(1)
let passwordValid = passwordTextField.rx_text.map{
    $0.characters.count >= minimalPasswordLength
    }.shareReplay(1)

将姓名和密码的输入框,文字类型的信号,根据长度,转换成了波尔类型的信号

map:通过对Observable发射映射的函数对每一项做转换

flatMap:将每个 Obserable 发射的数据变换为 Observable 的集合,然后将其 “拍扁”(降维 flatten)成一个 Observable。

scan:scan连续的对序列中的元素应用某一个元素。然后把结果作为下一次的输入

合并
当两个输入框输入长度都达标时,登录按钮才可以点击

let everythingValid = Observable.combineLatest(userNameValid, passwordValid) { $0 && $1 }.shareReplay(1)
              everythingValid.bindTo(loginButton.rx_enabled).addDisposableTo(disposeBag)

everythingValid.subscribeNext { [weak self] Bool in
    if (Bool) {
        self?.loginButton.backgroundColor = UIColor.redColor()
    }
    else {
        self?.loginButton.backgroundColor = UIColor.lightGrayColor()
    }
}.addDisposableTo(disposeBag)

合并了两个信号量,绑定给了button的enalbed属性,并且根据不同的enable信号,button的背景色不同。

combineLatest:当两个Observables中任意一个发送了数据,使用一个函数把两个Observable中最近的数据进行结合

startWith:在数据序列的开头增加一些数据

zip:它会等到Observable中的数据一一对应结合时,再发送数据

merge:合并多个 Observables 的组合成一个

switchLatest:将一个发射多个 Observables 的 Observable 转换成另一个单独的 Observable,后者发射那些 Observables 最近发射的数据项

demo地址:https://github.com/piang/iOSMVVMRxSwift

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值