RAC是什么?
①:RAC- ReactiveCocoa(RAC) GitHub 一个开源框架
②:RSC-函数响应编程框架
RAC有什么用?
帮助我们更简单霸气的处理事件
引入RAC 4.0.0
RAC里面最常见和常用的类!!!!
- 通过RACSignal:信号类 通过他创建一个信号!!(默认是冷信号!!)
- 通过订阅这个信号(变成:热信号!!)
3:等待发送信号!!
RACDisposable 它可以帮组我们取消订阅
①:信号发送完毕了,失败了。就要进行取消订阅
RACSubscriber(协议)订阅者(发送信号)
RACSubject 信号提供者!自己可以充当信号,又能发送信号! 即兼容RACSignal和RACSubscriber的功能
cocopoods使用这个命令进行安装第三方库,我的项目是使用的这些第三方库:
platform :ios, ‘8.0’
use_frameworks!
target '002-RAC' do
pod 'ReactiveObjC'
pod 'Masonry'
pod 'SDWebImage'
end
视频上使用的是这个第三方框架:
代码分析
#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// RACSignal: 信号类,当我们有数据产生,创建一个信号!
//1.创建信号(冷信号!)
//didSubscribe调用:只要一个信号被订阅就会调用!!
//didSubscribe作用:利用subscriber发送数据!!
RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"来了");
#warning 这个bloc块只有当订阅的时候也就是执行subscribeNext方法的时候才会调用
//3.发送数据subscriber由它来发送
[subscriber sendNext:@"呵呵哈哈嘿嘿"];
/*
//保存nextBlock代码块
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
*/
return nil;
}];
//2.订阅信号(热信号!!)
//nextBlock调用:只要订阅者发送数据就会调用!
//nextBlock作用:处理数据,展示UI界面!
//nextBlock内容:代码块内容就是subscribeNext传进去的代码块内容
[signal subscribeNext:^(id x) {
//x:信号发送的内容!!
NSLog(@"%@",x);
}];
}
RAC事件处理流程图
1.创建信号:RACDynamicSignal
解析:执行createSignal的时候,会执行下面这两个函数,也就是会保存Block块取名为didSubscribe(也就是createSignal传进去的代码块);最后返回RACDynamicSignal类型的信号( return [signal setNameWithFormat:@"+createSignal:"];)
解析代码:
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
2.订阅信号
解析:执行subscribeNext的时候,会执行下面这几个函数,也就是先创建订阅者RACSubscriber(RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
),然后保存Block块nextBlock(subscriber->_next = [next copy];
),最后真正的订阅信号,
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL]; //创建订阅者RACSubscriber,保存Block块nextBlock
return [self subscribe:o];//真正的订阅信号
}
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
subscriber->_next = [next copy];//保存Block块nextBlock
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
return subscriber;
}
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
subscriber->_next = [next copy];//保存订阅者
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
return subscriber;
}
#pragma mark Managing Subscribers
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
if (self.didSubscribe != NULL) {
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
RACDisposable *innerDisposable = self.didSubscribe(subscriber);//如果信号不存在,就直接发送消息,这个subscriber里面的代码块就是didSubscribe(也就是subscribeNext传进去的代码块);然后执行传进去的代码块,然后就直接调用 ```[subscriber sendNext:@"呵呵哈哈嘿嘿"];```发送消息(发送消息见第3点解说)
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
3:发送消息
//3.发送数据subscriber由它来发送
[subscriber sendNext:@"呵呵哈哈嘿嘿"];
#pragma mark RACSubscriber
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}