简介
ReactiveCocoa是github开源的一个第三方框架,响应式编程的代表。通过函数式响应式编程的思想,实现的信号机制。使用ReactiveCocoa去搭建MVVM架构,使代码更加高聚合,低耦合。便捷的实现双向绑定的效果。
集成
swift项目
pod 'ReactiveCocoa'
OC项目
pod 'ReactiveObjC'
swift与OC混编项目
pod 'ReactiveObjC'
pod 'ReactiveCocoa'
pod 'ReactiveObjCBridge'
常用类
RACSiganl信号类
//核心:信号类
//信号类作用:只要有数据改变,就会把数据长成一个信号,传递出去。
//只要有数据改变,就会有信号发出。
//数据发出,并不是信号类发出。
//创建信号
//RACDisposable
//RACSubscriber
//createSignal方法:
//1.创建RACDynamicSignal
//2.把didSubscribe保存到RACDynamicSignal
RACSignal *singal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
//block:当信号被订阅的时候就会调用
//block作用:描述当前信号哪些数据需要发送
//发送数据
NSLog(@"调用了didSubscribe");
//通常:传递数据出去。 发送
[subscriber sendNext:@1];
//如果信号被取消,就必须返回一个RACDisposable
return [RACDisposable disposableWithBlock:^{
//信号什么时候被取消: 1.自动取消:当一个信号订阅者subscriber被销毁时,就会自动取消订阅 2.手动取消
//block调用时刻:一旦一个信号被取消的时候就会调用
//block作用:当信号取消订阅时,用于清空一些资源
NSLog(@"取消了");
}];
}];
//订阅信号
// [singal subscribeNext:^(id _Nullable x) {
// NSLog(@"%@",x);
// }];
//只要订阅信号,就会返回一个取消信号的类
RACDisposable *disposable = [singal subscribeNext:^(id _Nullable x) {
//block:只要信号内部发送数据,就会调用这个block
NSLog(@"%@",x);
}];
//取消订阅
[disposable dispose];
//使用步骤
//1.创建信号
//2.订阅信号
// RACSingal底层实现
//1.当一个信号被订阅的时候,创建订阅者,并且把nextBlock保存到订阅者里面
//2.RACDynamicSignal subscribe:(id)subscriber
//3.调用RACDynamicSignal的didSubscribe
//4.[subscriber sendNext:@1];
//5.拿到订阅者的nextBlock调用。
RACSubject :信号提供者
//1.创建信号
RACSubject *subject = [RACSubject subject];
/*
//取消订阅用
_disposable = [RACCompoundDisposable compoundDisposable];
//确定容量 分配不同的内存 1.节约内存,2.提高性能
_subscribers = [[NSMutableArray alloc] initWithCapacity:1];
*/
//2.订阅信号
//创建一个数组在信号对象中,
//创建一个订阅者对象,将block回调保存到订阅者中,
//将订阅者保存到已经创建好的数组中。
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//3.发送信号
//遍历装有订阅者对象的数组,拿到这个订阅者对象,
//将block的内容拷贝,将value作为参数传入block,并且调用block执行
[subject sendNext:@"哈哈"];
RACReplaySubject:重复提供信号类
//RACReplaySubject:重复提供信号类
//如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复信号类
//创建信号
RACReplaySubject *replaySubject = [RACReplaySubject subject];
//订阅信号
//第一个订阅者
[replaySubject subscribeNext:^(id _Nullable x) {
NSLog(@"111111%@",x);
}];
//第二个订阅者
[replaySubject subscribeNext:^(id _Nullable x) {
NSLog(@"22222%@",x);
}];
//发送信号
[replaySubject sendNext:@77];
RACSequence:RAC中的集合类
//RACSequence:RAC中的集合类,用于代替数组和字典,可以进行快速遍历
NSArray *numbers = @[@1,@2,@3,@4,@5];
//.rac_sequence把数组转换成RAC中的集合类RACSequence
//把RACSequence转换成信号
[numbers.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
NSDictionary *dict = @{@"jack" : @"max",
@"andy" : @"min"
};
[dict.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
//RACTuple元组
RACTuple *touple = x;
NSLog(@"%@------%@",touple.first,touple.second);
//RACTupleUnpack 专门用来解析元组
RACTupleUnpack(NSString *key, NSString *value) = x;
NSLog(@"解析元组%@---%@",key,value);
}];
RACCommand 命令类
//RACCommand 命令类
//使用注意:RACCommand中的block不能返回一个nil的i信号
//创建命令类
RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
//block什么时候调用:当执行这个命令类的时候调用
NSLog(@"执行命令");
//block作用:描述下如何处理事件, 网络请求
NSLog(@"%@",input);
//返回数据
//为什么RACCommand必须返回信号
//处理事件的时候,肯定会有数据产生,产生的数据就通过返回的信号发出
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
//block作用:发送处理事件的信号
//block调用:当信号被订阅的时候才会调用
[subscriber sendNext:@"网络请求的数据"];
return nil;
}];
}];
//executionSignals信号源,包含事件处理的所有信号
//executionSignals:信号中的信号
//如果想接收信号源的信号内容,必须保证命令不会被销毁。 所以需要创建全局的RACCommand。
[command.executionSignals subscribeNext:^(id _Nullable x) {
RACSignal *singal = x;
[singal subscribeNext:^(id _Nullable x) {
NSLog(@"信号中的信号解析的数据%@",x);
}];
}];
//执行命令,调用signalBlock
[command execute:@9090];
RACMulticastConnection
//RACMulticastConnection:用于当一个信号,被多次订阅时,为了保证创建信号时,避免多次调用创建信号中的block,造成副作用,可以使用这个类处理。
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
NSLog(@"发送数据哈哈哈哈");
[subscriber sendNext:@6666];
return nil;
}];
//连接类
RACMulticastConnection *connection = [signal publish];
//订阅信号
[connection.signal subscribeNext:^(id _Nullable x) {
NSLog(@"x");
}];
[connection.signal subscribeNext:^(id _Nullable x) {
NSLog(@"x");
}];
//连接:才会把源信号编程热信号
[connection connect];
RAC常见用法
代理
//rac_signalForSelector 判断某个对象有没有调用他的某个方法,如果调用了,就会自动发送一个信号。
//可以用来替换代理
[[self rac_signalForSelector:@selector(helloTest)]subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"当前self调用了helloTest这个方法");
}];
- (void)helloTest
{
}
KVO
//KVO 代替
//监听某个对象的某个属性书否发生改变,如果发生改变,则会发送一个信号,订阅这个信号,就可以获得这个改变的值
[[_p rac_valuesForKeyPath:NSStringFromSelector(@selector(name)) observer:nil]subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
监听按钮
//监听按钮 _button只要产生UIControlEventTouchUpInside这个事件就会转换成信号,订阅这个信号就可以获取。
[[_button rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"点击了按钮hahaha ");
}];
监听通知
[[[NSNotificationCenter defaultCenter]rac_addObserverForName:UIKeyboardWillShowNotification object:nil]subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"监听键盘状态");
}];
监听textfield的输入内容
//监听textfield的输入内容
[[_testField rac_textSignal]subscribeNext:^(NSString * _Nullable x) {
NSLog(@"输入的内容:%@",x);
}];
多个界面都获取到数据之后,采取执行。
//多个界面都获取到数据之后,采取执行。 多个网络请求都获取到数据之后,再做操作。
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@"数据11111"];
return nil;
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@"数据22222"];
return nil;
}];
//RAC 可以判断两个信号有没有都发出内容
//当数组中的所有信号都发出的时候,self就会调用twoAll方法
//@selector(twoAllwithOne:two:)这个方法不能乱写,有几个信号就定义几个参数
//不需要主动订阅信号,这个方法会自动订阅这两个信号。
[self rac_liftSelector:@selector(twoAllwithOne:two:) withSignalsFromArray:@[signal,signal2]];
- (void)twoAllwithOne:(NSString *)oneStr two:(NSString *)twoStr
{
NSLog(@"两个信号都发出了 %@ ---- %@",oneStr,twoStr);
}
RAC常用宏
//把一个对象的某个属性绑定一个信号,只要发出信号,就会把信号的内容发送出去,给这个对象的属性赋值。
RAC(_label,text) = _testField.rac_textSignal;
//KVO 快速的监听对象的某个属性,改变的时候会发出信号。
[RACObserve(self.view, center) subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//把self转换成弱指针 循环引用问题
@weakify(self)
[RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
@strongify(self)
NSLog(@"%@",self.p);
return nil;
}];
//元组
//包装元组
RACTuple *tuple = RACTuplePack(@1,@3);
NSLog(@"%@-----%@",tuple.first,tuple.second);
//解包元组
RACTupleUnpack(NSNumber *number1, NSNumber *number2) = tuple;
NSLog(@"解包%@-----%@",number1,number2);