查看: 2041|回复: 0

[IOS开发教程] ReactiveObjC

发表于 2018-2-19 08:00:04
简介:

RAC 指的就是 RactiveCocoa ,是 Github 的一个开源框架,能够帮我们提供大量方便的事件处理方案,让我们更简单粗暴地去处理事件,现在分为 ReactiveObjC 和 ReactiveSwift ,两个框架的功能使用相似.

RAC 的核心思想:创建信号 - 订阅信号 - 发送信号.

Podfile文件:

  1. 1 platform :ios, '10.0'
  2. 2 target "RAC" do
  3. 3 pod 'ReactiveObjC', '~> 3.1.0'
  4. 4 use_frameworks!
  5. 5 end
复制代码


1. RACSignal 信号(主线程中执行)

  1. 1 // 创建信号
  2. 2 RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  3. 3 // 发送信号
  4. 4 [subscriber sendNext:@"发送信号"];
  5. 5 return nil;
  6. 6 }];
  7. 7
  8. 8 /* 订阅信号 */
  9. 9 RACDisposable *disposable = [signal subscribeNext:^(id _Nullable x) {
  10. 10
  11. 11 NSLog(@"信号内容:%@", x);
  12. 12 }];
  13. 13
  14. 14 // 取消订阅
  15. 15 [disposable dispose];
复制代码

结果:


2. RACSubject 信号(主线程中执行)

通常用来代替代理,有了它,就不必要定义代理了。

  1. 1 // 创建信号
  2. 2 RACSubject *subject = [RACSubject subject];
  3. 3 // 订阅信号(通常在别的视图控制器中订阅,与代理的用法类似
  4. 4 [subject subscribeNext:^(id _Nullable x) {
  5. 5 NSLog(@"信号内容:%@", x);
  6. 6 }];
  7. 7 [subject subscribeNext:^(id _Nullable x) {
  8. 8 // block调用时刻:当信号发出新值,就会调用.
  9. 9  NSLog(@"第二个订阅者%@",x);
  10. 10 }];
  11. 11 // 发送信号
  12. 12 [subject sendNext:@"发送信号"];
复制代码

结果:


3. RACTuple 元组(主线程中执行)

RAC 的元祖,跟我们 OC 的数组其实是一样的,它其实就是封装了我们 OC 的数组。

3.1

  1. 1 // 把值包装成 元组
  2. 2 RACTuple * tuple = RACTuplePack(@"abc",@"def",@"ghj");
  3. 3 // 解析元组
  4. 4 // RACTupleUnpack(NSString * a , NSString * b , NSString * c) = tuple ;
  5. 5 NSLog(@"RACTuple 元组包装: pack = %@ ",tuple);
复制代码

结果:

3.2 NSDictionary 元组 , 将字典里面的每一对 keyValue 列举出来(开了一个新的线程,异步列举)

  1. 1 NSDictionary * dicTuple = @{@"name":@"Jakey" , @"age":@18 , @"student":@(YES)};
  2. 2 [dicTuple.rac_sequence.signal subscribeNext:^(id _Nullable x) {
  3. 3 NSString * key = [(RACTuple *)x objectAtIndex:0];
  4. 4 id value = [(RACTuple *)x objectAtIndex:1];
  5. 5 NSLog(@"NSDictionary 元组使用 = %@ , key = %@ , value = %@ , thread = %@",x,key,value,[NSThread currentThread]);
  6. 6 }completed:^{
  7. 7 NSLog(@"NSDictionary 元组使用 completed , thread = %@",[NSThread currentThread]);
  8. 8 } ];
复制代码

结果:

3.3 NSArray 元组 ,将数组内的所有数据列举出来 (异步列举)

  1. 1 NSArray * array = @[@"klr",@"nop",@"rst"];
  2. 2 [array.rac_sequence.signal subscribeNext:^(id _Nullable x) {
  3. 3 NSLog(@"NSArray 元组 x = %@ , thread = %@",x,[NSThread currentThread]);
  4. 4 }error:^(NSError * _Nullable error) {
  5. 5 NSLog(@"NSArray 元组 error = %@",error);
  6. 6 } completed:^{
  7. 7 NSLog(@"NSArray 元组 completed ,thread = %@",[NSThread currentThread]);
  8. 8 }];
复制代码

结果:

3.4 异步列出 数组 或 字典 内容

  1. 1 NSArray * array = @[@"重装炮台111111111",@"追击潜能222222222222",@"警戒地雷333333333"];
  2. 2 NSArray * mapArray = [[array.rac_sequence map:^id _Nullable(id _Nullable value) {
  3. 3 NSLog(@"value = %@ , thread = %@",value,[NSThread currentThread]);
  4. 4 return [value stringByAppendingString:@" temp"];
  5. 5 }] array] ;
  6. 6 NSLog(@"===== %@", mapArray);
复制代码

结果:


4. RACReplaySubject 先发送 再订阅(主线程中执行)

先发送 再订阅 (这个比较 实用 ,可以在不知道什么时候发送信号的情况下准确的接收到信号)(主线程中执行)

  1. 1 // Capacity 事先预指订阅的个数,里面是动太数组
  2. 2 RACReplaySubject * replaySubject = [RACReplaySubject replaySubjectWithCapacity:2];
  3. 3
  4. 4 // 发送
  5. 5 [replaySubject sendNext:@"RACReplaySubjectDome 先发送 1"];
  6. 6 [replaySubject sendNext:@"RACReplaySubjectDome 先发送 2"];
  7. 7 [replaySubject sendCompleted];
  8. 8
  9. 9 // 订阅
  10. 10 [replaySubject subscribeNext:^(id _Nullable x) {
  11. 11 NSLog(@"subscribeNext:x = %@ error completed , thread = %@",x,[NSThread currentThread]);
  12. 12 } error:^(NSError * _Nullable error) {
  13. 13 NSLog(@"error = %@ , thread = %@",error,[NSThread currentThread]);
  14. 14 } completed:^{
  15. 15 NSLog(@"completed ! , thread = %@",[NSThread currentThread]);
  16. 16 }];
  17. 17
  18. 18 // 延时订阅,一样可以接收到信号
  19. 19 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  20. 20 [replaySubject subscribeNext:^(id _Nullable x) {
  21. 21
  22. 22 NSLog(@"subscribeNext: x = %@, thread = %@",x,[NSThread currentThread]);
  23. 23 }];
  24. 24 });
复制代码

结果:


5. RACMulticastConnection :广播连接(将 RACSignal 转成 RACMulticastConnection , block 在 main 主线程执行)

  1. 1 // 网络数据加载方法
  2. 2 -(void)loadDataFromNetwork:(void(^)(NSArray * dataArr))resultBlock
  3. 3 {
  4. 4 NSLog(@"loadDataFromNetwork selector thread = %@",[NSThread currentThread]);
  5. 5
  6. 6 resultBlock(@[@"temp = 1" , @"temp = 2" , @"temp = 3"]);
  7. 7 }
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12 - (RACSignal *)returnSignal {
  13. 13 // 不能解决 _view ( === self->_view , 这样就无法解决强引用的问题)
  14. 14 // __weak typeof(self) weakSelf = self ;
  15. 15
  16. 16 // 无论哪种用法都可以解决强引用问题
  17. 17 @weakify(self);
  18. 18
  19. 19 RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  20. 20 // @weakify(self) 配套使用
  21. 21 @strongify(self);
  22. 22 NSLog(@"connection createSignal , thread = %@",[NSThread currentThread]);
  23. 23
  24. 24 [self loadDataFromNetwork:^(NSArray *dataArr) {
  25. 25 NSLog(@"loadDataFromNetwork block dataArr = %@ , thread = %@",dataArr , [NSThread currentThread]);
  26. 26 // 发送信号
  27. 27 [subscriber sendNext:dataArr];
  28. 28 [subscriber sendCompleted]; //信号发送结束
  29. 29 }];
  30. 30
  31. 31 return [RACDisposable disposableWithBlock:^{
  32. 32 NSLog(@"connection disposableWithBlock ,thread = %@",[NSThread currentThread]);
  33. 33 }];
  34. 34 }];
  35. 35
  36. 36 return signal;
  37. 37 }
复制代码

5.1 直接订阅

  1. 1 // 直接订阅
  2. 2
  3. 3 RACSignal * signal = [self returnSignal];
  4. 4 [signal subscribeNext:^(id _Nullable x) {
  5. 5
  6. 6 NSLog(@"subscribeNext x = %@ , thread = %@",x,[NSThread currentThread]);
  7. 7
  8. 8 }];
复制代码

打印结果:

5.2 Signal 抓化为:Connection

  1. 1 // 将 signal 转化成 connection
  2. 2 RACMulticastConnection * connection = [signal publish];
  3. 3
  4. 4 // 订阅信号
  5. 5 // RACSubject:RACSubscriber
  6. 6 [connection.signal subscribeNext:^(id _Nullable x) {
  7. 7
  8. 8 NSLog(@"链接One x = %@ , thread = %@",x,[NSThread currentThread]);
  9. 9 }];
  10. 10 [connection.signal subscribeNext:^(id _Nullable x) {
  11. 11
  12. 12 NSLog(@"链接Two x = %@ , thread = %@",x,[NSThread currentThread]);
  13. 13 }];
  14. 14
  15. 15 // 连接
  16. 16 // RACSubject 订阅 RACSignal
  17. 17 [connection connect];
复制代码

打印结果:

6. RACCommand:处理事件的操作.(主线程中执行)

(1) RACCommand : 内部必须返回 RACSignal

(2) executionSignals : 信号外的信号

  (2.1) switchToLatest 最新发出来信号的 RACSignal 类型

  (2.2) 能过 (2.1)的诠释,那么只要用 switchToLatest subscribeNext: 订阅,就可以接收到发出来的信号

(3) 下面是执行的顺序,用 (index)表示

(4) execute:(id)input ; 该对象方法必须被调用(调用次数只有一次有效)才会执行一些相关操作,所有的 block 执行操作的 入口

  1. 1 RACCommand * command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
  2. 2 // input 即是执行 execute:(id)input; 传进来的值 (3)
  3. 3 NSLog(@"init RACCommand block 被执行 initWithSignalBlock input = %@ , thread = %@",input,[NSThread currentThread]);
  4. 4
  5. 5 return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  6. 6 // (6)
  7. 7 NSLog(@"内部创建的信号block 被执行 createSignal , thread = %@",[NSThread currentThread]);
  8. 8
  9. 9 // 发送信号
  10. 10 [subscriber sendNext:@"create Signal for somthing %@"];
  11. 11 [subscriber sendCompleted];
  12. 12
  13. 13 return [RACDisposable disposableWithBlock:^{
  14. 14 // 当 [subscriber sendCompleted] 调用时就会执行释放功能的 block (8)
  15. 15 NSLog(@"内部信号被释放 disposableWithBlock , thread = %@",[NSThread currentThread]);
  16. 16 }];
  17. 17
  18. 18 }];
  19. 19 }];
  20. 20
  21. 21 // 订阅最新发出来信号的 signal (7)
  22. 22 [command.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) {
  23. 23
  24. 24 NSLog(@"执行最近的 signal , x = %@ , thread = %@",x,[NSThread currentThread]);
  25. 25 }];
  26. 26
  27. 27 // executionSignals 这里传的 x 值类型为 RACDynamicSignal 类型对象 (5)
  28. 28 [command.executionSignals subscribeNext:^(id _Nullable x) {
  29. 29
  30. 30 NSLog(@"executionSignals subscribeNext x = %@ , thread = %@",x,[NSThread currentThread]);
  31. 31 }];
  32. 32
  33. 33 // 查看将要执行,每执行完一个步聚 都会调用一次查看哪个 signal block(即 第 x 个 block ) 将被使用 (2)(4)(9)
  34. 34 // signal 的 skip: 方法功能是跳过 skipCount 个 使用 block 的查看
  35. 35 [[[command executing] skip:0] subscribeNext:^(NSNumber * _Nullable x) {
  36. 36 NSLog(@"executing signal subscribeNext x = %@ , thread = %@",x,[NSThread currentThread]);
  37. 37 }];
  38. 38
  39. 39
  40. 40 // 只执行一次 (1)
  41. 41 [command execute:@"我要执行啦*****"];
复制代码

打印结果:


7.NSObject 分类中 rac_liftSelector… 方法的使用(即等待成所有的 RACSignal 对象发送完信号再执行方法) (主程中执行)
  1. 1 RACSignal * signalOne = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  2. 2
  3. 3 // 现在想发出信号了
  4. 4 [subscriber sendNext:@"网络请求数据 1"];
  5. 5
  6. 6 // 不需要释放操作
  7. 7 return nil ;
  8. 8 }];
  9. 9
  10. 10 RACSignal * signalTwo = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  11. 11
  12. 12 // 现在想发出信号了
  13. 13 [subscriber sendNext:@"网络请求数据 2"];
  14. 14
  15. 15 // 不需要释放操作
  16. 16 return nil ;
  17. 17 }];
  18. 18
  19. 19 [self rac_liftSelector:@selector(updateUIWithSignalOneMessage:signalTwoMessage:) withSignalsFromArray:@[signalOne , signalTwo]];
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27 // 当所有数据都拿到手后更新UI , 传的数据就是 signalOne 和 signalTwo 发出来的信号数据 ,(所以当前设计的接收方法 也必需要有两个参数,发出的信号按顺序 传参)
  28. 28 // 假如当前对象方法只设计 传一个参数,那么就会导致崩溃
  29. 29 -(void)updateUIWithSignalOneMessage:(id)signalOneMessage signalTwoMessage:(id)signalTwoMessage
  30. 30 {
  31. 31 NSLog(@"signalOneMessage = %@ , signalTwoMessage = %@ , thread = %@",signalOneMessage,signalTwoMessage,[NSThread currentThread]);
  32. 32 }
复制代码

打印结果:


8. NSNotificationCenter : 使用了 RAC 把监听通知的方法改成了 block 形式

  1. 1 // 监听通知
  2. 2 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidHideNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
  3. 3 NSLog(@"NSNotification 1 x = %@",x.userInfo);
  4. 4 }];
  5. 5
  6. 6 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidHideNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
  7. 7 NSLog(@"NSNotification 2 x = %@",x.userInfo);
  8. 8 }];
  9. 9
  10. 10 // 发出通知
  11. 11 [[NSNotificationCenter defaultCenter] postNotificationName:UIKeyboardDidHideNotification object:nil];
  12. 12
复制代码

打印结果:


9. RAC UITextField 监听 text 变化

  1. 1 // UITextField RAC使用
  2. 2 UITextField * textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 100, 50)];
  3. 3 textField.backgroundColor = [UIColor redColor];
  4. 4 [self.view addSubview:textField];
  5. 5
  6. 6 [[textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
  7. 7 NSLog(@"text = %@ , textField.text = %@ , thread = %@",x,textField.text,[NSThread currentThread]);
  8. 8 }];
  9. 9
  10. 10
  11. 11 // 绑定 lable.text
  12. 12 UILabel * lable = [[UILabel alloc] initWithFrame:CGRectMake(100, 200, 100, 50)];
  13. 13 lable.backgroundColor = [UIColor greenColor];
  14. 14 [self.view addSubview:lable];
  15. 15
  16. 16 // 绑定 lable.text 永远等于 textField.text
  17. 17 RAC(lable,text) = textField.rac_textSignal ;
复制代码

输入为: China Welcome

打印结果:


10. RAC KVO 监听属性内容变化
  1. 1 [RACObserve(self, age) subscribeNext:^(id _Nullable x) {
  2. 2
  3. 3 NSLog(@"KVO 监听到 age 内容发生变化 ,变为 %@ , thread = %@",x,[NSThread currentThread]);
  4. 4 }];
  5. 5
  6. 6
  7. 7
  8. 8 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  9. 9 {
  10. 10 self.age++ ;
  11. 11 }
复制代码

打印结果:


11. RACSignal 的 bind 绑定

bind 里面的做法:

(1) 创建一个 RACSignal 对象做为 bind 方法的返值;

(2) 当我们拿到该返的 RACSignal 类对象 tempSignal 去进行订阅;

(3) 然后会执行创建 RACSignal 对象时的 block A (RACSignalBindBlock),并在里面执行 bindBlock 拿到 返回的 block B (RACSignal)(返回值为 RACSignal 对象);

(4) 再执行 block B 就拿到 RACReturnSignal 对象;

(5) RACReturnSignal 对象 进行订阅,然后在该订阅 block 里面拿到 value 值;

(6) tempSignal 的 subscriber 订阅者 发送信号值 value , 最后在外面 tempSignal 对象的订阅就接收到信息了。

  1. 1 UITextField * textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 300, 150)];
  2. 2 textField.backgroundColor = [UIColor yellowColor];
  3. 3 [self.view addSubview:textField];
  4. 4
  5. 5 [[textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{
  6. 6
  7. 7 NSLog(@"绑定 block");
  8. 8
  9. 9 return ^RACSignal * (id _Nullable value, BOOL *stop){
  10. 10
  11. 11 NSLog(@"返回block的值为 = %@",value);
  12. 12
  13. 13 return [RACReturnSignal return:value];
  14. 14 };
  15. 15
  16. 16 }] subscribeNext:^(id _Nullable x) {
  17. 17 NSLog(@"signal subscribeNext x = %@",x);
  18. 18 }];
复制代码

打印结果:


12. RACReplaySubject 对象的 then: 方法

then 功能:可以使 RACSignal 及其子类的 对象有序接收信号

  1. 1 // 在这里尽量使用 RACReplaySubject 类 ,因为 RACReplaySubject 可以先发送信号,订阅代码可以放在之后写。
  2. 2 // 如果 使用 RACSignal 或 RACSubject ,那么必须要等这些对象订阅完后,发送的信号才能接收的到
  3. 3 RACReplaySubject * subjectA = [RACReplaySubject subject];
  4. 4
  5. 5 // 这就是好处,先发送
  6. 6 [subjectA sendNext:@"AA"];
  7. 7 // 必须要调用这个方法才会来到 then 后的 block
  8. 8 [subjectA sendCompleted];
  9. 9
  10. 10 // 按指定的顺序接收到信号
  11. 11 [[[subjectA then:^RACSignal * _Nonnull{
  12. 12
  13. 13 // 当 subjectA 发送信号完成后 才执行 当前的 block
  14. 14 RACReplaySubject * subjectB = [RACReplaySubject subject];
  15. 15
  16. 16 // 可以单独调用发送信号完成的方法就可以接着执行下一个 then
  17. 17 [subjectB sendCompleted];
  18. 18
  19. 19 return subjectB ;
  20. 20
  21. 21 }] then:^RACSignal * _Nonnull{
  22. 22
  23. 23 // 当 subjectB 发送信号完成后 才执行 当前的 block
  24. 24 RACReplaySubject * subjectC = [RACReplaySubject subject];
  25. 25
  26. 26 // subjectC 发送信号
  27. 27 [subjectC sendNext:@"CC"];
  28. 28
  29. 29 return subjectC ;
  30. 30
  31. 31 }] subscribeNext:^(id _Nullable x) { // 这个就 "相当于" 订阅了 subjectC 对象(但真正的对象则不是 subjectC 对象) ,x = @"CC"
  32. 32 NSLog(@"RACReplaySubject C x = %@",x);
  33. 33 }];
复制代码

打印结果:


13. 合并两个及以上 RACSignal 或 RACSignal 的子类对象,用新创建的 RACSignal 对象接收多个 RACSignal 或 RACSignal 的子类对象 发出的信号

  1. 1 RACReplaySubject * subjectA = [RACReplaySubject subject];
  2. 2 RACReplaySubject * subjectB = [RACReplaySubject subject];
  3. 3 RACReplaySubject * subjectC = [RACReplaySubject subject];
  4. 4
  5. 5 // 三个对象发送信号(只需其中一个或多个发送信号时,合并的 信号对象 都可以在订阅的 block 接收到信息)
  6. 6 [subjectB sendNext:@"BB"];
  7. 7 [subjectA sendNext:@"AA"];
  8. 8 [subjectC sendNext:@"CC"];
  9. 9
  10. 10 // 合并两个信号对象变成一个接收信号对象 subjectD , subjectD 订阅 接收 subjectB 和 subjectA 发送的信号
  11. 11 [[[subjectA merge:subjectB] merge:subjectC] subscribeNext:^(id _Nullable x) {
  12. 12 NSLog(@"%@",x);
  13. 13 }];
复制代码

打印结果:


14. 压缩两个及以上 RACSignal 或 RACSignal 的子类对象,用新创建的 RACSignal 对象同时接收多个 RACSignal 或 RACSignal 的子类对象 发出的信号

  1. 1 RACReplaySubject * subjectA = [RACReplaySubject subject];
  2. 2 RACReplaySubject * subjectB = [RACReplaySubject subject];
  3. 3 RACReplaySubject * subjectC = [RACReplaySubject subject];
  4. 4
  5. 5 // 三个对象同时发送信号,缺一不可
  6. 6 [subjectA sendNext:@"信号AA"];
  7. 7 [subjectB sendNext:@"信号BB"];
  8. 8 [subjectC sendNext:@"信号CC"];
  9. 9
  10. 10 // 合并两个信号对象变成一个接收信号对象 subjectD , subjectD 订阅 接收 subjectB 和 subjectA 发送的信号
  11. 11 // x 类型为 元组 RACTwoTuple 类型:解析使用
  12. 12 [[[subjectA zipWith:subjectB] zipWith:subjectC] subscribeNext:^(id _Nullable x) {
  13. 13 // 注意:元组需要 一层一层 地解析
  14. 14 RACTupleUnpack(RACTuple * AB , NSString * C) = x ;
  15. 15 NSLog(@"x的值为:%@",x);
  16. 16
  17. 17 RACTupleUnpack(NSString * A , NSString * B) = AB ;
  18. 18 NSLog(@"AB的值为:%@",AB);
  19. 19
  20. 20 NSLog(@"A = %@ , B = %@ , C = %@",A , B , C);
  21. 21 }];
复制代码

打印结果:


15. 合并两个及以上 RACSignal 或 RACSignal 的子类对象,用新创建的 RACSignal 对象 同时接收多个 RACSignal 或 RACSignal 的子类对象 发出的信号

公共的代码:

  1. 1 RACReplaySubject * subjectA = [RACReplaySubject subject];
  2. 2 RACReplaySubject * subjectB = [RACReplaySubject subject];
  3. 3 RACReplaySubject * subjectC = [RACReplaySubject subject];
  4. 4
  5. 5 // 三个对象同时发送信号,缺一不可
  6. 6 [subjectA sendNext:@"邮件AA"];
  7. 7 [subjectB sendNext:@"邮件BB"];
  8. 8 [subjectC sendNext:@"邮件CC"];
复制代码

方法一:

  1. 1 //也可以把那些信号传的参数聚合成一个值
  2. 2 // 遵守 NSFastEnumeration 协议的类都可成为数组
  3. 3 // reduce block 参数可以自己根据信号设置
  4. 4 [[RACSignal combineLatest:@[subjectA,subjectB,subjectC] reduce:^id (NSString * signalA,NSString * signalB,NSString * signalC){
  5. 5
  6. 6 // 把这 三个中任意 一个发出的信号值 聚合成一个值 NSString 类型
  7. 7
  8. 8 return [NSString stringWithFormat:@"A = %@ , B = %@ , C = %@",signalA , signalB , signalC];
  9. 9
  10. 10 }] subscribeNext:^(id _Nullable x) {
  11. 11 NSLog(@"聚合后三个值变成一个 NSString 类型的值: %@",x);
  12. 12 }];
复制代码

打印结果:

方法二:

  1. 1 // 也可以用聚合绑定做法
  2. 2 UILabel * lable = [[UILabel alloc] initWithFrame:CGRectMake(30, 60, 380, 100)];
  3. 3 [self.view addSubview:lable];
  4. 4 lable.backgroundColor = [UIColor redColor];
  5. 5 RAC(lable , text) = [RACSignal combineLatest:@[subjectA,subjectB,subjectC] reduce:^id (NSString * signalA,NSString * signalB,NSString * signalC){
  6. 6
  7. 7 // 把这 三个中任意 一个发出的信号值 聚合成一个值 NSString 类型
  8. 8
  9. 9 return [NSString stringWithFormat:@"A = %@ , B = %@ , C = %@",signalA , signalB , signalC];
  10. 10
  11. 11 }];
  12. 12
  13. 13 NSLog(@"lable.text = %@",lable.text);
复制代码

打印结果:


16. RACSignal 的 map 拦截信号发出的信号和处理数据
  1. 1 RACReplaySubject * signal = [RACReplaySubject subject];
  2. 2
  3. 3 [[signal map:^id _Nullable(id _Nullable value) {
  4. 4 return [NSString stringWithFormat:@"%@ (拦截发出的信号,拼接个想要的东西)",value];
  5. 5 }] subscribeNext:^(id _Nullable x) {
  6. 6 NSLog(@"接收到处理后的信息 = %@",x);
  7. 7 }];
  8. 8
  9. 9 [signal sendNext:@"@(当前信号的信息是Welcome Orange World)"];
复制代码

结果:


17. 信号中的信号,RACSignal 的 flattenMap 对象方法,用来接收信号对象value 和 信号对象value发出的信息
  1. 1 RACReplaySubject * signal = [RACReplaySubject subject];
  2. 2 RACSubject * subject = [RACSubject subject];
  3. 3
  4. 4 [[signal flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
  5. 5
  6. 6 // value 是信号对象 == subject
  7. 7
  8. 8 return [value map:^id _Nullable(id _Nullable value) {
  9. 9
  10. 10 return [NSString stringWithFormat:@"(添加拦截信号处理信号) (%@)",value];
  11. 11 }];
  12. 12 }] subscribeNext:^(id _Nullable x) {
  13. 13 NSLog(@"接收到处理后的信息 = %@",x);
  14. 14 }];
  15. 15
  16. 16 [signal sendNext:subject];
  17. 17
  18. 18 [subject sendNext:@" subject 发出信号了"];
复制代码

结果:


18. 信号过滤器:RACSignal 的 filter: 方法,用来设置一个条件发出的信号才会被接收到
  1. 1 RACReplaySubject * replaySubject = [RACReplaySubject replaySubjectWithCapacity:1];
  2. 2
  3. 3 // filter block 是一个过滤器,只有满足条件发出的信号才会被接收到
  4. 4 [[replaySubject filter:^BOOL(id _Nullable value) {
  5. 5
  6. 6 return ((NSString *)value).length >= 6 ;
  7. 7
  8. 8 }] subscribeNext:^(id _Nullable x) {
  9. 9
  10. 10 NSLog(@"接收到信号 = %@",x);
  11. 11 }];
  12. 12
  13. 13 // // 发出的信号长度为 5 时,订阅收不到信号信息
  14. 14 // [replaySubject sendNext:@"12345"];
  15. 15
  16. 16 // 发出的信号长度为 >= 6 时,订阅收到信号了信息
  17. 17 [replaySubject sendNext:@"123456"];
复制代码

结果:


19.RACSignal 信号对象 与 定时器的关系

公用变量:

  1. 1 // 定时器
  2. 2 // TimeInterval : 间隔时间,秒
  3. 3 // repeats : 是否重复
  4. 4 // blokc : 调用代码块 (在主线程中执行)
  5. 5 if (@available(iOS 10.0, *)) {
  6. 6 [NSTimer scheduledTimerWithTimeInterval:1 repeats:NO block:^(NSTimer * _Nonnull timer) {
  7. 7 NSLog(@"每隔一秒调用一次当前 block , thread = %@",[NSThread currentThread]);
  8. 8 }];
  9. 9 } else {
  10. 10 }
复制代码

方法一:

  1. 1 // RACSignal 制定定时器
  2. 2 // interval : 间隔的时间,秒
  3. 3 /**
  4. 4 onScheduler : 多线程 , 队列
  5. 5 mainThreadScheduler : 主线程中 执行订阅代码块
  6. 6 currentScheduler : 在当前创建时的线程中 执行订阅代码块
  7. 7 */
  8. 8 /**
  9. 9 schedulerWithPriority: 或 schedulerWithPriority:name: 优先级 , name 表示线程名
  10. 10 // 优先级高,开起 新的线程
  11. 11 RACSchedulerPriorityHigh = DISPATCH_QUEUE_PRIORITY_HIGH,
  12. 12 // 默认优先级,开起 新的线程
  13. 13 RACSchedulerPriorityDefault = DISPATCH_QUEUE_PRIORITY_DEFAULT,
  14. 14 // 优先级低,开起 新的线程
  15. 15 RACSchedulerPriorityLow = DISPATCH_QUEUE_PRIORITY_LOW,
  16. 16 // app 进入后台也可以调用,开起 新的线程
  17. 17 RACSchedulerPriorityBackground = DISPATCH_QUEUE_PRIORITY_BACKGROUND,
  18. 18 */
  19. 19
  20. 20 [[RACReplaySubject interval:1 onScheduler:[RACScheduler schedulerWithPriority:RACSchedulerPriorityLow]] subscribeNext:^(NSDate * _Nullable x) {
  21. 21 // x 是当前的时间
  22. 22 NSLog(@"每隔一秒调用订阅代码:x = %@ , 在线程 thread = %@",x,[NSThread currentThread]);
  23. 23 }];
复制代码

打印结果:

方法二:

  1. 1 [NSTimer scheduledTimerWithTimeInterval:1 repeats:NO block:^(NSTimer * _Nonnull timer) {
  2. 2 NSLog(@"每隔一秒调用一次当前 block , thread = %@",[NSThread currentThread]);
  3. 3 }];
  4. 4
  5. 5 [[[RACReplaySubject createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  6. 6
  7. 7 [subscriber sendNext:@"~~2秒后调用订阅 block"];
  8. 8
  9. 9 return nil ;
  10. 10 }] delay:2] // 延时 5秒 再
  11. 11 subscribeNext:^(id _Nullable x) {
  12. 12
  13. 13 NSLog(@"-------------%@",x);
  14. 14 }];
复制代码

结果:



回复

使用道具 举报