本demo详见github
下面我们来看看RAC的常见的类的使用
1.RAC常见类-RACSiganl
RACSiganl.h
#import <UIKit/UIKit.h>
@interface RACSiganl : UIViewController
@end
RACSiganl.m
#import "RACSiganl.h"
#import <ReactiveObjC.h>
@interface RACSiganl ()
@end
@implementation RACSiganl
- (void)viewDidLoad {
[super viewDidLoad];
[self way1];
NSLog(@"===================================");
[self way2];//简写的方式
}
-(void)way1{
// 1.创建信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 3.发送信号
[subscriber sendNext:@"要发送的内容"];
// 4.取消信号,如果信号想要被取消,就必须返回一个RACDisposable
// 信号什么时候被取消:1.自动取消,当一个信号的订阅者被销毁的时候机会自动取消订阅,2.手动取消,
//block什么时候调用:一旦一个信号被取消订阅就会调用
//block作用:当信号被取消时用于清空一些资源
return [RACDisposable disposableWithBlock:^{
NSLog(@"取消订阅");
}];
}];
// 2. 订阅信号
//subscribeNext
// 把nextBlock保存到订阅者里面
// 只要订阅信号就会返回一个取消订阅信号的类
RACDisposable *disposable = [signal subscribeNext:^(id x) {
// block的调用时刻:只要信号内部发出数据就会调用这个block
NSLog(@"======%@", x);
}];
// 取消订阅
[disposable dispose];
}
-(void)way2{
[[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"1.创建了信号");
[subscriber sendNext:@"要发送的内容"];
NSLog(@"4.发送信号完毕");
return nil;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"2.订阅了信号");
NSLog(@"3.收到了内容:%@",x);
}];
}
@end
RACSignal总结:
- 1.核心:
- (1)核心:信号类
- (2)信号类的作用:只要有数据改变就会把数据包装成信号传递出去
- (3)只要有数据改变就会有信号发出
- (4)数据发出,并不是信号类发出,信号类不能发送数据
- 2.使用方法:
- (1)创建信号
- (2)订阅信号
- 3.实现思路:
- (1)当一个信号被订阅,创建订阅者,并把nextBlock保存到订阅者里面。
- (2)创建的时候会返回 [RACDynamicSignal createSignal:didSubscribe];
- (3)调用RACDynamicSignal的didSubscribe
- (4)发送信号[subscriber sendNext:value];
- (5)拿到订阅者的nextBlock调用
我们通过源码分析:(command+鼠标左键)



2.RAC常见类-RACSubject
RACSubject_1.m
#import "RACSubject_1.h"
#import <ReactiveObjC.h>
#import "RACSubject_2.h"
@interface RACSubject_1 ()
@property (nonatomic,strong)UIButton *btn;
@end
@implementation RACSubject_1
- (void)viewDidLoad {
[super viewDidLoad];
self.btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 500, 300, 100)];
[self.btn setTitle:@"开始" forState:UIControlStateNormal];
[self.btn setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.btn];
[self.btn addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside];
}
-(void)jump{
RACSubject_2 *vc = [[RACSubject_2 alloc]init];
vc.subject =[RACSubject subject];
@weakify(self);//防止循环引用
[vc.subject subscribeNext:^(id _Nullable x) {
@strongify(self);
[self.btn setTitle:x forState:UIControlStateNormal];
}];
[self.navigationController pushViewController:vc animated:YES];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
RACSubject_2.h
#import <UIKit/UIKit.h>
@class RACSubject;
@interface RACSubject_2 : UIViewController
@property (nonatomic,strong)RACSubject *subject;
@end
RACSubject_2.m
#import "RACSubject_2.h"
#import <ReactiveObjC.h>
@interface RACSubject_2 ()
@property (nonatomic,strong)UIButton *btn;
@end
@implementation RACSubject_2
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 500, 300, 100)];
[self.btn setTitle:@"返回" forState:UIControlStateNormal];
[self.btn setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.btn];
[self.btn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
}
-(void)back{
[self.subject sendNext:@"返回了哟"];
[self.navigationController popViewControllerAnimated:YES];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
分析:我们可以通过RACSubject来实现界面的反向传值
步骤:
// 1.创建信号
RACSubject *subject = [RACSubject subject];
// 2.订阅信号
[subject subscribeNext:^(id x) {
// block:当有数据发出的时候就会调用
// block:处理数据
NSLog(@"%@",x);
}];
// 3.发送信号
[subject sendNext:value];
**注意:~~**
RACSubject和RACReplaySubject的区别
RACSubject必须要先订阅信号之后才能发送信号, 而RACReplaySubject可以先发送信号后订阅.


3.RAC常见类-RACDisposable
#import "RACDisposable_.h"
#import <ReactiveObjC.h>
@interface RACDisposable_ ()
@property (nonatomic,strong)id<RACSubscriber> subscriber;
@end
@implementation RACDisposable_
- (void)viewDidLoad {
[super viewDidLoad];
//创建信号(冷信号)
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
//发送信号
[subscriber sendNext:@"1"];
//n保存订阅者,不会t让他自动消失
self->_subscriber = subscriber;
return [RACDisposable disposableWithBlock:^{
NSLog(@"取消订阅啦");
}];
}];
//订阅信号(热信号)
RACDisposable *disposable = [signal subscribeNext:^(id _Nullable x) {
//信号接收处
NSLog(@"%@",x);
}];
//默认一个信号发送完毕会自动取消订阅的
//因为是用属性 来保存了
//手动取消订阅
[disposable dispose];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
分析:自己可以注释掉[disposable dispose];看看执行的顺序(dealloc)
4.RAC常见类-RACReplaySubject
RACReplaySubject_1.m
#import "RACReplaySubject_1.h"
#import <ReactiveObjC.h>
#import "RACReplaySubject_2.h"
@interface RACReplaySubject_1 ()
@property (nonatomic,strong)UIButton *btn;
@property (nonatomic,strong)RACReplaySubject *subject;
@end
@implementation RACReplaySubject_1
- (void)viewDidLoad {
[super viewDidLoad];
self.btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 500, 300, 100)];
[self.btn setTitle:@"开始" forState:UIControlStateNormal];
[self.btn setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.btn];
[self.btn addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside];
// 1.创建信号
RACReplaySubject *subject = [RACReplaySubject subject];
// 2.订阅信号
[subject subscribeNext:^(id x) {
NSLog(@"第一个订阅者%@",x);
}];
[subject subscribeNext:^(id x) {
NSLog(@"第二个订阅者%@",x);
}];
// 3.发送信号
[subject sendNext:@1];
[subject sendNext:@2];
self.subject = subject;
}
-(void)jump{
RACReplaySubject_2 *vc = [[RACReplaySubject_2 alloc]init];
vc.subject = self.subject;
[self.navigationController pushViewController:vc animated:YES];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
RACReplaySubject_2.h
#import <UIKit/UIKit.h>
@class RACReplaySubject ;
@interface RACReplaySubject_2 : UIViewController
@property (nonatomic, strong) RACReplaySubject *subject;
@end
RACReplaySubject_2.m
#import "RACReplaySubject_2.h"
#import <ReactiveObjC.h>
@interface RACReplaySubject_2 ()
@property (nonatomic,strong)UIButton *btn;
@end
@implementation RACReplaySubject_2
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 500, 300, 100)];
[self.btn setTitle:@"返回" forState:UIControlStateNormal];
[self.btn setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.btn];
[self.btn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
}
-(void)back{
[self.subject sendNext:@"返回了哟"];
[self.navigationController popViewControllerAnimated:YES];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
分析:可以先订阅,然后在发送信号哟
5.RAC常见类-RACSequence
#import "RACSequence_.h"
#import <ReactiveObjC.h>
@interface RACSequence_ ()
@end
@implementation RACSequence_
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *arr = @[@"1",@"2",@"3"];
NSDictionary*dict =@ {@"key1":@"vaule1",@"key2":@"vaule2",@"key3":@"vaule3"};
//快速遍历字典
[dict.rac_sequence.signal subscribeNext:^(id _Nullable x) {
// NSString*key = x[0];
// NSString*value = x[1];
RACTupleUnpack(NSString*key,NSString*value) = x;
NSLog(@"%@--%@",key,value);
} error:^(NSError * _Nullable error) {
NSLog(@"error");
} completed:^{
NSLog(@"over");
}];
//快速遍历数组
[arr.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
} error:^(NSError * _Nullable error) {
NSLog(@"error");
} completed:^{
NSLog(@"over");
}];
}
@end
在开发中:点击屏幕开始字典数组转模型数组。开发中可以快速高效的遍历数组和字典、字典转模型等
6.RAC常见类-RACCommand
#import "RACCommand_.h"
#import <ReactiveObjC.h>
@interface RACCommand_ ()
@end
@implementation RACCommand_
- (void)viewDidLoad {
[super viewDidLoad];
// [self test1];
NSLog(@"-----------------------------------");
// [self test2];
NSLog(@"-----------------------------------");
//[self test3];
NSLog(@"-----------------------------------");
// [self test4];
NSLog(@"-----------------------------------");
[self test5];
}
// 普通做法
- (void)test1 {
// RACCommand: 处理事件
// 不能返回空的信号
// 1.创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
//block调用,执行命令的时候就会调用
NSLog(@"%@",input); // input 为执行命令传进来的参数
// 这里的返回值不允许为nil
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"执行命令产生的数据"];
return nil;
}];
}];
// 如何拿到执行命令中产生的数据呢?
// 订阅命令内部的信号
// ** 方式一:直接订阅执行命令返回的信号
// 2.执行命令
RACSignal *signal =[command execute:@2]; // 这里其实用到的是replaySubject 可以先发送命令再订阅
// 在这里就可以订阅信号了
[signal subscribeNext:^(id x) {
NSLog(@"----%@",x);
}];
}
// 一般做法
- (void)test2 {
// 1.创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
//block调用,执行命令的时候就会调用
NSLog(@"%@",input); // input 为执行命令传进来的参数
// 这里的返回值不允许为nil
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"执行命令产生的数据"];
return nil;
}];
}];
// 方式二:
// 订阅信号
// 注意:这里必须是先订阅才能发送命令
// executionSignals:信号源,信号中信号,signalofsignals:信号,发送数据就是信号
[command.executionSignals subscribeNext:^(RACSignal *x) {
[x subscribeNext:^(id x) {
NSLog(@"=====%@", x);
}];
NSLog(@"----%@", x);
}];
// 2.执行命令
[command execute:@2];
}
// 高级做法
- (void)test3 {
// 1.创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// block调用:执行命令的时候就会调用
NSLog(@"%@", input);
// 这里的返回值不允许为nil
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"发送信号"];
return nil;
}];
}];
// 方式三
// switchToLatest获取最新发送的信号,只能用于信号中信号。
[command.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 2.执行命令
[command execute:@3];
}
// switchToLatest
- (void)test4 {
// 创建信号中信号
RACSubject *signalofsignals = [RACSubject subject];
RACSubject *signalA = [RACSubject subject];
// 订阅信号
// [signalofsignals subscribeNext:^(RACSignal *x) {
// [x subscribeNext:^(id x) {
// NSLog(@"%@", x);
// }];
// }];
// switchToLatest: 获取信号中信号发送的最新信号
[signalofsignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 发送信号
[signalofsignals sendNext:signalA];
[signalA sendNext:@4];
}
// 监听事件有没有完成
- (void)test5 {
//注意:当前命令内部发送数据完成,一定要主动发送完成
// 1.创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// block调用:执行命令的时候就会调用
NSLog(@"----%@", input);
// 这里的返回值不允许为nil
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 发送数据
[subscriber sendNext:@"执行命令产生的数据"];
// *** 发送完成 **
[subscriber sendCompleted];
return nil;
}];
}];
// 监听事件有没有完成
[command.executing subscribeNext:^(id x) {
NSLog(@"===%@",x);
if ([x boolValue] == YES) { // 正在执行
NSLog(@"当前正在执行%@", x);
}else {
// 执行完成/没有执行
NSLog(@"执行完成/没有执行");
}
}];
// 2.执行命令 [command execute:@"哈哈"];
RACSignal *signal= [command execute:@"哈哈"];
[signal subscribeNext:^(id x) {
NSLog(@"----%@",x);
}];
}
@end
RACCommand:RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程,比如看事件有没有执行完毕
使用场景:监听按钮点击,网络请求
7.RAC常见类-RACMulticastConnection
#import "RACMulticastConnection_.h"
#import <ReactiveObjC.h>
@interface RACMulticastConnection_ ()
@end
@implementation RACMulticastConnection_
- (void)viewDidLoad {
[super viewDidLoad];
[self test];
NSLog(@"---------");
[self test2];
}
- (void)test // 普通写法, 这样的缺点是:每订阅一次信号就得重新创建并发送请求,这样很不友好
{
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// didSubscribeblock中的代码都统称为副作用。
// 发送请求---比如afn
NSLog(@"发送请求啦");
// 发送信号
[subscriber sendNext:@"请求的内容"];
return nil;
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
}
- (void)test2 { // 比较好的做法。 使用RACMulticastConnection,无论有多少个订阅者,无论订阅多少次,我只发送一个。
// 1.发送请求,用一个信号内包装,不管有多少个订阅者,只想发一次请求
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 发送请求
NSLog(@"发送请求啦");
// 发送信号
[subscriber sendNext:@"请求的内容"];
return nil;
}];
//2. 创建连接类
RACMulticastConnection *connection = [signal publish];
[connection.signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[connection.signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[connection.signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
//3. 连接。只有连接了才会把信号源变为热信号
[connection connect];
}
@end
打印 :
发送请求啦
请求的内容
发送请求啦
请求的内容
发送请求啦
请求的内容
---------
发送请求啦
请求的内容
请求的内容
请求的内容
分析:
- 第一种:只要subscribeNext一次,里面就会创建一个订阅者对象,传到createSignal的block里面,然后发送信号内容(执行3次)
- 第二种:包装到一个里面,3个一次性发出信号内容
- 即:当有多个订阅者,但是我们只想发送一个信号的时候怎么办?这时我们就可以用RACMulticastConnection,来实现
友情链接:
网友评论