美文网首页
RAC(ReactiveCocoa----ReactiveObj

RAC(ReactiveCocoa----ReactiveObj

作者: 孙伟胜 | 来源:发表于2020-10-25 15:40 被阅读0次

文章内容:

代理
简单使用
基于UIKitFoundation (Foundation对象)
RACSubject冷信号和热信号
KVO事件信号
网络请求
RACCommand
RACMulticastConnection
信号的调度器RACScheduler(线程)
RACChannelTo

代理

- (RACSignal<RACTuple *> *)rac_signalForSelector:(SEL)selector;
- (RACSignal<RACTuple *> *)rac_signalForSelector:(SEL)selector fromProtocol:(Protocol *)protocol;

简单使用

//信号创建
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        //任何时候,都可以发送信号,可以异步
        [subscriber sendNext:@"发送信号"];
        //数据传递结束,最好调用sendCompleted,代表命令执行结束
        [subscriber sendCompleted];
        return nil;
    }];
    //信号订阅
    RACDisposable *disposable = [signal subscribeNext:^(id  _Nullable x) {
        //收到信号;
        NSLog(@"收到的信号内容");
    }];
    self.keyboardDisposable = disposable;

    //取消订阅
    [disposable dispose];

基于UIKit

//1. rac_textSignal 文本监听信号,可以减少对代理方法的依赖
//UITextField创建了一个 `textSignal`的信号,并订阅了该信号
// 当UITextField的内容发生改变时,就会回调subscribeNext
//当UITextField内输入的内容长度大于5时,才会回调subscribeNext
//2. filter 订阅的信号进行筛选
    [[[textFid rac_textSignal] filter:^BOOL(NSString * _Nullable value) {
          return value.length > 5;
    }] subscribeNext:^(NSString * _Nullable x) {
          NSLog(@"filter result = %@",  x);
    }];

//3. ignore 对订阅的信号进行过滤
    [[[textFid rac_textSignal] ignore:@"666"] subscribeNext:^(NSString * _Nullable x) {
        //当输入的内容 equalTo @"666" 时,这里不执行
        //其他内容,均会执行subscribeNext
        NSLog(@"ignore = %@", x);
    }];
//UIButton rac_signalForControlEvents 创建事件监听信号
//当UIButton点击时,会调用subscribeNext
[[button rac_signalForControlEvents:(UIControlEventTouchUpInside)] subscribeNext:^(__kindof UIControl * _Nullable x) {
        NSLog(@"666");
                UIViewController *secVC = [[CTMediator sharedInstance] YQ_createSearchCoursesViewControllerWithForwardSource:@""];
        
     // UIViewController *secVC = [[CTMediator sharedInstance] performTarget:@"SecondVCRouter" action:@"createSearchCoursesViewController" params:nil shouldCacheTarget:NO];
        [self presentViewController:secVC animated:YES completion:nil];
    }];
// 手势 信号
    [[tapGesture rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
        NSLog(@"tapGesture");
        @strongify(self);
        [self.viewModel.clickAdCommand execute:nil];//RACCommand 执行
    }];

Foundation (Foundation对象)

//1.NSNotificationCenter 通知
    //NSNotificationCenter  监听了APP退到后台的事件。最重要的一点就是不需要移除通知,比通知用起来更爽,无后顾之忧!!!
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"NSNotificationCenter UIApplicationDidEnterBackgroundNotification");
    }];
    
    @property (nonatomic, strong) RACDisposable *keyboardDisposable;
    self.keyboardDisposable = [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil]  subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"%@ 键盘弹起", x); // x 是通知对象
    }];
//注意:rac_addObserverForName同样需要移除监听。RAC通知监听会返回一个RACDisposable清洁工的对象,在dealloc中销毁信号,信号销毁时,RAC在销毁的block中移除了监听
// 2、 interval定时器 (程序进入后台,再重新进入前台时,仍然有效,内部是用GCD实现的)
    
    //创建一个定时器,间隔1s,在主线程中运行
    RACSignal *timerSignal = [RACSignal interval:1.0f onScheduler:[RACScheduler mainThreadScheduler]];
    //定时器总时间3秒
    timerSignal = [timerSignal take:6];
    //定义一个倒计时的NSInteger变量
    self.counter = 6;
    @weakify(self)
    [timerSignal subscribeNext:^(id  _Nullable x) {
        @strongify(self)
        self.counter--;
        NSLog(@"count = %ld", (long)self.counter);
    } completed:^{
        //计时完成
        NSLog(@"Timer completed");
    }];
// 3、delay延迟
    //创建一个信号,2秒后订阅者收到消息
    [[[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        return nil;
    }] delay:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"delay : %@", x);
    }];
// 3.数组遍历。rac_sequence
    NSArray *array = @[@"8", @"2", @"6", @"4", @"3"];
    [array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"数组内容:%@", x);
    }];
// 5、NSDictionary字典遍历  Tuple 元组
    NSDictionary *dictionary = @{@"key1":@"value1", @"key2":@"value2", @"key3":@"value3",@"key4":@"value4", @"key5":@"value5", @"key3":@"value3",@"key1":@"value1", @"key2":@"value2", @"key3":@"value3"};
    [dictionary.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
        // x 是一个元祖,这个宏能够将 key 和 value 拆开   乱序
        RACTupleUnpack(NSString *key, NSString *value) = x;
        NSLog(@"Tuple字典内容:%@ : %@", key, value);
    }];

RACSubject

RACSubjectRACSignal 对象之上进行了简单的修改,将原有的冷信号改造成了热信号,将不可变变成了可变。

  1. 这个类即可以创建信号, 也可以发送信号

  2. RACSubject时间相关的,订阅者接收到多少值取决于它订阅的时间。

  3. RACSubjectRACSignalRACSubcriber 的结合体。(实现了 RACSubscriber 协议)

冷信号和热信号

冷信号是被动的,只会在被订阅时向订阅者发送通知;热信号是主动的,它会在任意时间发出通知,与订阅者的订阅时间无关。

也就是说冷信号所有的订阅者会在订阅时收到完全相同的序列;而订阅热信号之后,只会收到在订阅之后发出的序列。

热信号的订阅者能否收到消息取决于订阅的时间。

//6、RACSubject代理
DelegateView.h
@interface DelegateView : UIView
@property (nonatomic, strong) RACSubject *delegateSignal;
@end
DelegateView.m
//触发 发送消息
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 判断代理信号是否有值
    if (self.delegateSignal) {
        // 有值,给信号发送消息
        [self.delegateSignal sendNext:@666];
    }
}
Controller
//使用前,记得初始化。
//注意 必须先订阅,再发送消息才可以接收到消息。
self.delegageView.delegateSignal = [RACSubject subject];
[self.delegageView.delegateSignal subscribeNext:^(id  _Nullable x) {
  //订阅到 666 的消息
  NSLog(@"RACSubject result = %@", x);
}];
7. //RACReplaySubject
/**
     只要发送信号 都可以在订阅的block中收到信号。
     */
    // 创建信号
    RACReplaySubject *replaySubject = [RACReplaySubject subject];
    // 订阅信号
    [replaySubject subscribeNext:^(id x) {
        NSLog(@"订阅者一接收到信号: %@", x);
    }];
    // 发送数据
    [replaySubject sendNext:@"hello, RAC."];

    // 订阅信号
    [replaySubject subscribeNext:^(id x) {
        NSLog(@"订阅者二接收到信号: %@",x);
    }];
******打印****** RACObjC[9640:87566] 订阅者一接收到信号: hello, RAC.
******打印****** RACObjC[9640:87566] 订阅者二接收到信号: hello, RAC.
#pragma mark  对比RACSubject
    /**
     必须先订阅,再发送消息才可以接收到信号。
     */
    // 创建信号
    RACSubject *subject = [RACSubject subject];
    
    // 订阅信号
    [subject subscribeNext:^(id x) {
        NSLog(@"订阅者二接收到信号: %@",x);
    }];
    
    // 发送数据
    [subject sendNext:@"hello, RAC."];
    
    // 订阅信号
       [subject subscribeNext:^(id x) {
           NSLog(@"订阅者一接收到信号: %@", x);
       }];
****打印***** RACObjC[9585:85299] 订阅者二接收到信号: hello, RAC.

KVO

//1、rac_valuesForKeyPath 通过keyPath监听
    [[self.delegageView rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id  _Nullable x) {
        NSLog(@"kvo = %@", x);
    }];
    self.delegageView.frame = CGRectMake(10, 210, 200, 200);//当DeletateView的Frame发生变化的时候收到消息。
// 2、RACObserve 属性监听
      // 在进行监听时,同样可以使用filter信号,对值进行筛选
    // @property (nonatomic, assign) NSInteger KVOObject;
    [[RACObserve(self, self.KVOObject) filter:^BOOL(id  _Nullable value) {
        return [value intValue] >= 2;
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"RACObserve : value = %@", x);
    }];
    self.KVOObject = 1;//当KVOObject属性的值大于等于2的时候,收到信号。
//3. RAC 事件绑定
    //当UITextField输入的内容为@"666"时,bView视图的背景颜色变为grayColor
    RAC(self.delegageView, backgroundColor) = [self.textFid.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        return [value isEqualToString:@"666"] ? [UIColor grayColor] : [UIColor greenColor];
    }];
//登录框 用户名和密码输入正确时,登录按钮才可以点击

事件信号

//1、RACTuple 元祖
    //只能存储OC对象 可以用于解包或者存储对象
    //解包数据 如:三.5 字典遍历
    // RACTupleUnpack(NSNumber *a, NSNumber *b) = x;
    
// 2、bind 包装
    //获取到信号返回的值,包装成新值, 再次通过信号返回给订阅者
    [[self.textFid.rac_textSignal bind:^RACSignalBindBlock _Nonnull{
        return ^RACSignal *(id value, BOOL *stop){
            return [RACSignal return:[NSString stringWithFormat:@"hello %@", value]];
        };
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"bind %@", x);
    }];
    
// 3、concat 合并
    //按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号
    
    RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"A"];
        [subscriber sendCompleted];
        return nil;
    }];
    RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"B"];
        [subscriber sendCompleted];
        return nil;
    }];
    // 把signalA拼接到signalB后,signalA发送完成,signalB才会被激活 顺序执行
    [[signalA concat: signalB] subscribeNext:^(id  _Nullable x) {
        //先拿到 signalA 的结果 , 再拿到 signalB 的结果 , 执行两次
        NSLog(@"concat %@", x);
    }];
    
//4、then 下一个
    //用于连接两个信号,当第一个信号完成,才会连接then返回的信号
    // 底层实现  1.使用concat连接then返回的信号  2.先过滤掉之前的信号发出的值
    [[[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendCompleted];
        return nil;
    }] then:^RACSignal *{
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            //可以对第一个信号的数据进行过滤处理 , 不能直接获得第一个信号的数据返回值
            [subscriber sendNext:@2];
            return nil;
        }];
    }] subscribeNext:^(id x) {
        // 只能接收到第二个信号的值,也就是then返回信号的值
        NSLog(@"then : %@",x); // 2
    }];
    
//5.merge 合并
    // 把多个信号合并为一个信号,任何一个信号有新值的时候就会调用
    // 创建多个信号
    RACSignal *mergeSignalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        return nil;
    }];
    RACSignal *mergeSignalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@2];
        return nil;
    }];
    // 合并信号,只要有信号发送数据,都能监听到.
    RACSignal *mergeSignal = [mergeSignalA merge:mergeSignalB];

    [mergeSignal subscribeNext:^(id x) {
        //每次获取单个信号的值
        NSLog(@"merge : %@",x);
    }];
    
//6、zipWith 压缩
    /**
     把两个信号压缩成一个信号,只有当两个信号都发出一次信号内容后,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件(组合的数据都是一一对应的)
     */
    RACSignal *zipSignalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendNext:@2];
        return nil;
    }];
    RACSignal *zipSignalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        //1秒后执行
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@10];
        });
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@20];
        });

        return nil;
    }];

    RACSignal *zipSignal = [zipSignalA zipWith:zipSignalB];

    [zipSignal subscribeNext:^(id  _Nullable x) {
        // x 是一个元祖
        RACTupleUnpack(NSNumber *a, NSNumber *b) = x;
        NSLog(@"zip with : %@   %@", a, b);
        //第一次输出   1  10
        //第二次输出   2  20
    }];
    
// 7.combineLatest 结合
    /**
     将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号 (combineLatest 与 zipWith不同的是,每次只拿各个信号最新的值)
     */
    RACSignal *combineSignalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendNext:@2];
        return nil;
    }];

    RACSignal *combineSignalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@3];
        });
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@5];
        });

        return nil;
    }];

    RACSignal *combineSignal = [combineSignalA combineLatestWith:combineSignalB];

    [combineSignal subscribeNext:^(id  _Nullable x) {
        // x 是一个元祖
        RACTupleUnpack(NSNumber *a, NSNumber *b) = x;
        NSLog(@"combineLatest : %@   %@", a, b);
        //第一次输出 2 3
        //第二次输出 2 5
        // 因为combineSignalA中的2是最新数据,所以,combineSignalA每次获取到的都是2
    }];
    
// 8、reduce 聚合
    //用于信号发出的内容是元组,把信号发出元组的值聚合成一个值,一般都是先组合在聚合
    RACSignal *reduceSignalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@1];
        return nil;
    }];

    RACSignal *reduceSignalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@3];
        return nil;
    }];

    RACSignal *reduceSign = [RACSignal combineLatest:@[reduceSignalA, reduceSignalB] reduce:^id _Nonnull(NSNumber *a, NSNumber *b){
        //reduce中主要是对返回数据的处理
        return [NSString stringWithFormat:@"%@ - %@", a, b];
    }];
    [reduceSign subscribeNext:^(id  _Nullable x) {
        NSLog(@"reduce %@", x);// a - b
    }];
    
//9、map 数据过滤
    /**
     map 的底层实现是通过flattenMap 实现的。map 直接对数据进行处理,并且返回处理后的数据
     */
    [[self.textFid.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        // 当源信号发出,就会调用这个block,修改源信号的内容
        // 返回值:就是处理完源信号的内容。
        return [NSString stringWithFormat:@"hello : %@",value];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"Map : %@",x); // hello: "x"
    }];
    
//10、flattenMap 信号过滤
    /**
     flattenMap 的底层实现是通过bind实现的。拿到原数据,处理完成之后,包装成信号返回
     */
    [[self.textFid.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
        return [RACSignal return:[NSString stringWithFormat:@"hello : %@", value]];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"flattenMap %@", x);
    }];
// 11、filter 过滤
    //过滤信号,获取满足条件的信号 参考TextFid RAC
    [[self.textFid.rac_textSignal filter:^BOOL(NSString *value) {
        return value.length > 6;
    }] subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"filter : %@", x); // x 值位数大于6
    }];
    
    /**
     flatternMap和Map的区别:
     
     FlatternMap中的Block返回信号
     Map中的Block返回对象
     开发中,如果信号发出的值不是信号,映射一般使用Map
     开发中,如果信号发出的值是信号,映射一般使用FlatternMap
     */

网络请求

//使用 @weakify(self) 和 @strongify(self) 避免循环引用
    @weakify(self)
    [[ViewModel getCourseInfoByTime:0 isExperience:isExperience] subscribeNext:^(id  _Nullable x) {
        @strongify(self)
        //接口请求成功,订阅者可以在这里获取到接口返回的内容 x
    } error:^(NSError * _Nullable error) {
        @strongify(self)
        //当接口出错时,这里可以处理错误信息
    }];
/**
 解读:(RAC的执行流程)
 1、在ViewModel类中,创建了一个信号,这个信号请求了一个获取课程的接口。信号创建之后,并不会立即执行,要等订阅者,订阅并调用subscribeNext时,才会执行。
 2、在ViewController中,经过用户操作,开始调用getCourseByIsExperience方法。此时,订阅者开始订阅信号,信号中的createSignal开始执行接口请求方法。
 3、当接口请求成功后,根据状态,将对应的object或者error通过sendNext: 和sendError:传递给订阅者
 4、订阅者开始执行subscribeNext 或者 error block中的代码
 (ps:如果接口请求之后,不需要获取返回值,则可以在信号中这样返回 [subscriber sendNext:nil])

优点:这个接口请求过程,ViewController只需要将接口所需参数传入,即可得到接口的结果,大大简化了控制器层面的内容,使得控制器更加专注于页面之间的业务处理,数据传递等功能。
 */

RACCommand

两种创建方式:

/*
第一种就是直接通过传进一个用于构建RACSignal的block参数来初始化RACCommand,
而block中的参数input为执行command时传入的数据,
另外,创建出的signal可在里面完成一些数据操作,如网络请求,本地数据库读写等等,
而第二种则另外还需要传进一个能传递BOOL事件的RACSignal,
这个signal的作用相当于过滤,当传递的布尔事件为真值时,command能够执行,反之则不行。
*/
- (id)initWithSignalBlock:(RACSignal * (^)(id input))signalBlock;  ①
- (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock;  ②

注意: 伴随着command一
起构建的signal,记得要在操作完成后发送完成消息以表示其执行完了:否则不能再执行此command。

[subscriber sendCompleted];

RACCommand的执行使用下面的这个函数:第一种方式创建的时候作为input参数接收

- (RACSignal *)execute:(id)input;

订阅RACCommand我们可以使用其内部的属性executionSignals返回一个信号,然后对这个信号进行订阅。

//x是一个RACSignal类型的信号
[[aCommand executionSignals]
   subscribeNext:^(id x) {
       NSLog(@"%@",x);
   }];

在订阅的block中,我们打印了传递事件x的描述,最后会发现x原来是一个RACSignal,原因是RACCommand中的executionSignals属性是一个包裹着信号的信号,其包裹着的信号就是我们当初在创建RACCommand时进行构建的信号,所以当我们开始执行RACCommand时,executionSignals信号就会立即发送事件,传递出其包裹的信号,我们可以对这个信号进行订阅:

//如果你想在RACCommand执行时做某些提示操作(弹出等待框,出现转来转去的菊花),并在执行后取消提示,你可以这样写:
[[aCommand executionSignals]
    subscribeNext:^(RACSignal *x) {//对X进行订阅
         //  开始提示
        [x subscribeNext:^(id x) {
         //  关闭提示
            //  Do something...
        }];
    }];

switchToLatest 转换写法

[[[aCommand executionSignals]switchToLatest]
    subscribeNext:^(id x) {
        //  Do something...
    }];

错误处理

[aCommand.errors
    subscribeNext:^(NSError *x) {
        NSLog(@"ERROR! --> %@",x);
}];

RACCommand 一般先订阅再执行。 execute 使用的是 RACReplaySubject, 所以可以先执行命令, 再订阅信号

// RACCommand 
    // 使用场景: 1.监听按钮点击事件; 2.发送网络请求等;
    
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        NSLog(@"%@", input);
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [subscriber sendNext:@"执行命令产生的数据"];
            return nil;
        }];
    }];
    
    RACSignal *signal = [command execute:@"执行命令"];
    
    // execute 使用的是 RACReplaySubject, 所以可以先执行命令, 再订阅信号
    [signal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

理解:**

使用场景: 1.监听按钮点击事件; 2.发送网络请求等;

  1. View 中发生(或者Controller)中 触发(点击/手势)。

    - (RACSignal *)execute:(id)input;
    
  2. viewModel中

    创建RACCommand,走一些逻辑代码 [返回RACSignal (发送消息)] 和 错误返回。

  3. 控制器中

    订阅block块中 得到消息(值)。

RACMulticastConnection

// 需求: 每次订阅信号时不要都发送网络请求, 只发送一次网络请求, 但是每次订阅信号时都要能得到数据

// 1.创建信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // connection connect 时执行此 block.
        NSLog(@"网络请求");
        [subscriber sendNext:@"JSON数据"];
        return nil;
    }];
    
    // 2.信号转换成连接类
    //RACMulticastConnection *connection = [signal publish];
    RACMulticastConnection *connection = [signal multicast:[RACReplaySubject subject]];
    
    // 3.订阅连接类的信号
    [connection.signal subscribeNext:^(id x) {
        // subscriber sendNext 时执行此 block
        NSLog(@"订阅者一: %@",x);
    }];
    [connection.signal subscribeNext:^(id x) {
        // subscriber sendNext 时执行此 block
        NSLog(@"订阅者二: %@",x);
    }];
    
    // 4.连接
    [connection connect];
    ******输出******* 
2020-05-11 15:05:25.350601+0800 RACObjC[12517:200796] 网络请求
2020-05-11 15:05:25.350705+0800 RACObjC[12517:200796] 订阅者一: JSON数据
2020-05-11 15:05:25.351078+0800 RACObjC[12517:200796] 订阅者二: JSON数据
多次请求网络版本
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"网络请求");
        [subscriber sendNext:@"JSON数据"];
        return nil;
    }];
    [signal subscribeNext:^(id x) {
        NSLog(@"订阅者一: %@", x);
    }];
    [signal subscribeNext:^(id x) {
        NSLog(@"订阅者二: %@", x);
    }];
    ******输出******* 
2020-05-11 15:05:25.349379+0800 RACObjC[12517:200796] 网络请求
2020-05-11 15:05:25.349932+0800 RACObjC[12517:200796] 订阅者一: JSON数据
2020-05-11 15:05:25.350118+0800 RACObjC[12517:200796] 网络请求
2020-05-11 15:05:25.350219+0800 RACObjC[12517:200796] 订阅者二: JSON数据

信号的调度器RACScheduler
deliverOn

//创建信号
    -(void)createUpSignals{
    RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"sendTestSignal%@",[NSThread currentThread]);
        [subscriber sendNext:@1];
        [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{
                }];
        }];
    self.testSignal = signal;
    }

    //订阅信号
    //要想放在主线程执行只要将[RACScheduler scheduler]更换为[RACScheduler mainThreadScheduler]
    [[self.testSignal deliverOn:[RACScheduler scheduler]] subscribeNext:^(id x) {
        NSLog(@"receiveSignal%@",[NSThread currentThread]);
    }];
********打印结果*********  
2016-09-02 09:48:59.697 Signal processing[1686:22894] sendTestSignal<NSThread: 0x7fb373c0bb80>{number = 1, name = main}
2016-09-02 09:48:59.697 Signal processing[1686:24680] receiveSignal<NSThread: 0x7fb373e07070>{number = 3, name = (null)}

subscribeOn则会将传递内容和副作用一起放到指定线程执行

 [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"sendSignal%@",[NSThread currentThread]);
        [subscriber sendNext:@1];
        return [RACDisposable disposableWithBlock:^{
                }];
    }] subscribeOn:[RACScheduler scheduler]] subscribeNext:^(id x) {
        NSLog(@"receiveSignal%@",[NSThread currentThread]);
    }];
**********打印结果*********
2016-09-02 09:54:47.819 Signal processing[1778:54504] sendSignal<NSThread: 0x7fde7adb4e00>{number = 2, name = (null)}
2016-09-02 09:54:47.819 Signal processing[1778:54504] receiveSignal<NSThread: 0x7fde7adb4e00>{number = 2, name = (null)}

RACChannelTo

RACChannelTo(self, name) = RACChannelTo(self.model, name);

这是一个双向绑定,self.name和self.model.name任何一个改变,另外一个也会改变

写在最后。
不断学习不断进步,如有差错,望指出,共同学习

相关文章

网友评论

      本文标题:RAC(ReactiveCocoa----ReactiveObj

      本文链接:https://www.haomeiwen.com/subject/dkhnmktx.html