最近在做MVVM项目改造,绕不开reactivecocoa(rac),学习过程中做的一些简单的笔记,用于快速上手,后续实战中遇到的问题也会慢慢更新。
常用类主要分为三大类:
1.RACSignal类
简述:RAC的核心功能信号量,本身是冷信号,不起作用,需要订阅之后才会变成热信号从而生效。
订阅方法:- (RACDisposable *)subscribeNext:(void (^)(ValueType _Nullable x))nextBlock;
常用场景:
详情可见reactivecocoa里的XXX-RACSignalSupport类,为UIControl等控件提供了支持方法,例如:
[[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) { }];
可以将按钮的点击方法转化成信号量,订阅之后就可以执行点击操作。
2.RACSubject类
RACSubject除了本身是信号量之外,还可以发送信号;
RACSubject *subject = [RACSubject subject];
[subject sendNext:@(YES)];
[subject subscribeNext:^(id _Nullable x) { }];
从这个角度来看,这个功能就和我们平时用到的delegate和block类似了,所以我们将它用于单向传递的操作,也就是以前使用block和delegate的地方这里都可以替换成RACSubject,至于为什么要替换呢?不替换行不行呢?个人理解是可以的,个人觉得MVVM项目改造的时候,使用RACSubject只是为了使业务逻辑统一收纳到ViewModel中,方便管理。
3.RACCommand类
RACCommand类可以理解成是一个request+response的组合,A告知B需要做什么,B做完之后反馈给A,A->B->A这样的场景用到RACCommand会多一些。MVVM项目改造过程中,用到比较多的场景是,view需要重新请求刷新界面,于是,view告知ViewModel请求数据,ViewModel请求完数据,然后处理数据,处理完数据之后,再告知view刷新界面。
RACCommand初始化的时候需要一个RACSignal,在这个RACSignal内部,我们需要自己手动发送信号,并且需要调用sendCompleted方法告知我们信号发送完毕。
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
// do something
[subscriber sendNext:@(YES)];
[subscriber sendCompleted];
return nil;
}];
}];
订阅RACCommand的信号:
[[command executionSignals] subscribeNext:^(id _Nullable x) {
// x是创建command时的racsignal
[x subscribeNext:^(id _Nullable x) {
// x是我们手动sendNext的值
}];
}];
这里executionSignals是返回一个来自于RACCommand的信号。
调用RACCommand我们可以选择手动调用也可以选择和控件绑定
// 手动调用
[command execute:nil];
// 和button绑定
button.rac_command = command;
4.其他
reactivecocoa有一些非常实用的宏,@weakify和@strongify就不说了,功能和YY系列的类似。
RACObserve(TARGET, KEYPATH) 快添加观察者
RAC(TARGET, ...) = RACObserve(TARGET, KEYPATH) 快速实现绑定
5.踩坑
1.项目为swift和OC混编的时候,通过cocoapods导入时需要使用user_framework!