RAC 最基本的东西-- RACSignal

基础用法

  • 创建信号
  • 订阅信号
  • 发送信号
1
2
3
4
5
6
7
8
9
10
// 1.创建信号(cold)
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 3.发送信号
[subscriber sendNext:@"hello, RAC."];
return nil;
}];
// 2.订阅信号(hot)
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];

在创建 RACSignal 的时候,

1
+ (RACSignal<ValueType> *)createSignal:(RACDisposable * _Nullable (^)(id<RACSubscriber> subscriber))didSubscribe;

方法传入的 block 会返回一个 RACDisposable 对象。

将以上代码中的 return nil; 替换成如下代码

1
2
3
4
return [RACDisposable disposableWithBlock:^{
// 订阅者释放时会自动取消订阅信号, 但是只要订阅者没有释放, 就不会取消订阅信号.
NSLog(@"信号被取消订阅了!");
}];

这个时候在 [subscriber sendComplete] 的时候会执行创建 RACDisposable 传入的 block

如何主动取消订阅

1
2
3
4
5
_disposable = [signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];// 可以看出来,这里的 subscribeNext 返回的就是取消订阅这个 signal 的 RACDisoisable
// 不管 在创建 signal 的时候 return 的是 nil 还是 RACDisposable 对象
[_disposable dispose]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#import "ViewController.h"
#import <ReactiveObjC.h>
@interface ViewController ()
@property (nonatomic, strong) RACDisposable *disposable;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber ) {
[subscriber sendNext:@"hello, RAC."];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"2"];
});
});
});
});
});
});
});
});
});
// 如果信号不再发送数据, 最好调用信号的发送完成方法, 该方法会调用 [RACDisposable disposable] 取消订阅信号.
//[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// 订阅者释放时会自动取消订阅信号, 但是只要订阅者没有释放, 就不会取消订阅信号.
NSLog(@"信号被取消订阅了!");
}];
//如果取消订阅的时候不需要做什么事情, return nil 也没有关系
//return nil;
}];
_disposable = [signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 主动取消订阅信号
[_disposable dispose];
}
@end

timer

1
2
3
[[RACSignal interval:2.0 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];

delay

1
2
3
4
5
6
7
8
9
NSLog(@"first");
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"send,signal"];
return nil;
}]
delay:2.0] // 信号延迟两秒
subscribeNext:^(id x) {
NSLog(@"%@",x);
}];

timeout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"send,signal"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"send,signal2"];
});
return nil;
}] timeout:2.0 onScheduler:[RACScheduler currentScheduler]];
// 2s 后发送错误信号。2s 之后的信号被忽略
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
} error:^(NSError *error) {
NSLog(@"%@",error);
}];

retry

重试, 遇到 error 就会重新执行创建信号中的block,直到成功. 也可以传入 retry 的次数,如果超过这个次数还是 error 则返回 error

对 RACSignal 的操作

1
2
3
4
5
6
7
8
9
10
11
12
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"5"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"6"];
});
return nil;
}];

map 映射

map

1
2
3
4
5
6
7
8
9
10
11
12
/*
Map使用步骤:
1.传入一个block,类型是返回对象,参数是value
2.value就是源信号的内容,直接拿到源信号的内容做处理
3.把处理好的内容,直接返回就好了,不用包装成信号,返回的值,就是映射的值。
*/
[[signal map:^id _Nullable(id _Nullable value) {
return @([value integerValue] * 10);
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 10,20,30,50,30,60

flattenMap

把源信号的内容映射成一个新的信号,信号可以是任意类型。

1
2
3
4
5
6
7
8
9
10
11
12
/*
flattenMap使用步骤:
1.传入一个block,block类型是返回值RACStream,参数value
2.参数value就是源信号的内容,拿到源信号的内容做处理
3.包装成RACReturnSignal信号,返回出去。
*/
[[signal flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
return [RACReturnSignal return:[NSString stringWithFormat:@"%@%@",value,value]];
}]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];

flattenmap 和 map 的区别

  1. FlatternMap中的Block返回信号。
  2. Map中的Block返回对象。
  3. 开发中,如果信号发出的值不是信号,映射一般使用Map
  4. 开发中,如果信号发出的值是信号,映射一般使用flatternMap。

mapReplace

传入一个值 x , 将每个信号的值都改为 x

1
2
3
4
5
[[signal mapReplace:@"4"]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 4,4,4,4,4,4,4

filter 过滤

filter

传入一个 block , 当这个 block 返回 YES 的时候才能响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"5"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"6"];
return nil;
}];
[[signal filter:^BOOL(id _Nullable value) {
// 只有 value 为 @“3” 的时候才进入下一步
return [value isEqualToString:@"3"];
}]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];

ignore

传入一个参数 x 忽略 value == x 的信号

1
2
3
4
5
[[signal ignore:@"3"]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 1,2,5,6

distinctUntilChanged

如果这次受到的信号 value 跟上次的信号 value 相同, 这次信号被忽略。

1
2
3
4
5
[[signal distinctUntilChanged]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 1,2,3,5,3,6

startWith

传入一个参数 x , 订阅的时候首先收到 value = x 的信号。 类似于在创建 RACSignal 的第一行 [subscriber sendNext:x];

1
2
3
4
5
[[signal startWith:@"1"]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 1,1,2,3,3,5,3,6

take

传入一个数组 n, 表明只响应前 n 个信号

1
2
3
4
5
[[signal take:3]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 1,2,3

takeLast

传入一个数值 n, 取最后 n 个信号

只有收到了complete才知道结果。

takeUntilBlock

一直响应,直到传入的 block 第一次返回 YES

1
2
3
4
5
6
7
[[signal takeUntilBlock:^BOOL(id _Nullable x) {
return [x isEqualToString:@"5"];
}]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 1,2,3,3

takeWhileBlock

一直响应,直到传入的 block 第一次返回 NO

1
2
3
4
5
6
7
[[signal takeWhileBlock:^BOOL(id _Nullable x) {
return [x integerValue] < 5;
}]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 1,2,3,3

skip

传入一个数字 n 表明忽略前面第 n 个信号, 第 n + 1 个信号开始响应。

1
2
3
4
5
[[signal skip:3]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 3,5,3,6

skipUntilBlock

一直忽略信号, 直到传入的 block 第一次返回 YES

1
2
3
4
5
6
7
[[signal skipUntilBlock:^BOOL(id _Nullable x) {
return ![x isEqualToString:@"1"];
}]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 2,3,3,5,3,6

skipWhileBlock

一直忽略信号, 直到传入的 block 第一次返回 NO

1
2
3
4
5
6
7
[[signal skipWhileBlock:^BOOL(id _Nullable x) {
return [x isEqualToString:@"1"];
}]
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 2,3,3,5,3,6

scanWithStart:reduce

解决类似数组求和的问题

1
2
3
4
5
6
7
RACSequence *number = @[@1,@2,@3,@4].rac_sequence;
RACSequence *sums =[number scanWithStart:@2 reduce:^id _Nullable(NSNumber *running, NSNumber *next) {
return @(running.integerValue + next.integerValue);
}];
// 第一个参数是起点值, 第二个是便利的block block 中第一个是上一次便利的结果, 第二个是当前位置的值
NSLog(@"%@", sums.array);
//3,5,8,12

组合

contact

把signalA拼接到signalB后,signalA发送完成,signalB才会被激活。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"1"];
[subscriber sendCompleted];// 必须conpleted 才会到第二个 signal
});
return nil;
}];
RACSignal *singnal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"11"];
return nil;
}];
RACSignal *contact = [signal concat:singnal2];
[contact subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 1,11

then

类似 contact 将两个 signal 链接

  1. 只有等第一个 signal 介绍之后才会激活第二个 signal。
  2. 在第一个 signal 结束之前 signal2 的信号会被忽略。
  3. 第一个 signal 只关注 complete sendNext 被忽略

区别: contact signal1 的 sendNext 会响应, 而 then 的不会。

1
2
3
4
// signal complete 发出之后 signal 的信号才会响应.
RACSignal *then = [signal then:^RACSignal * _Nonnull{
return singnal2;
}];

merge

将两个 signal 合并为一个 signal 原先的信号发出 都会响应, 没有前后顺序。

1
2
3
4
RACSignal *merge = [signal merge:singnal2];
[merge subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];

zip

将两个signal 合并之后的 next 合并为一个 tuple 返回回来。 一一对应关系,一个信号的 next 等到第二个信号有 next 之后 包装成 signal 返回。
返回的 zip 第一个值就是第一个信号的next。

combineLatest

将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号。

zip 和 combineLatest 的区别

1
2
3
4
5
6
7
signal1-----1----2-----3------4-------5-------6--------7-----
signal2----------------5----------------------7--------------
combine 返回 (3,5) (6,7)
zip 返回 (1,5) (2,7)
CepheusSun wechat
订阅我的公众号,每次更新我都不一定会告诉你!
坚持原创技术分享,您的支持将鼓励我继续创作!
0%