美文网首页
ReactiveObjC(一)

ReactiveObjC(一)

作者: Code_人生 | 来源:发表于2019-08-13 17:16 被阅读0次

RACDisposable disposable 销毁
RACScheduler scheduler 调度
RACCommand command 命令
RACSignal signal 信号
RACSubject subject
RACReplaySubject
RACStream
RACSequence sequence 序列
RACTuple tuple 元组,重数
RACSubscriber subscribe 订阅
RACCompoundDisposable compound 复合的;混合的

ReactiveObjC.png

1、信号映射:map、flattenMap
2、信号过滤:filter、ignore、distinctUntilChanged
3、信号合并:combineLatest、reduce、merge、zipWith
4、信号连接:concat、then
5、信号操作时间:timeout、interval、dely
6、信号取值:take、takeLast、takeUntil
7、信号跳过:skip
8、信号发送顺序:donext、completed
9、获取信号中的信号:switchToLatest
10、信号错误重试:retry

创建信号、订阅信号、发送信号、销毁信号

https://github.com/ReactiveCocoa/ReactiveObjC
pod 'ReactiveObjC'
导入头文件 #import <ReactiveObjC.h>

基本使用一
    //1.创建信号 创建信号对象 然后创建一个可变数组!
    RACSubject * subject = [RACSubject subject];
    //2.订阅信号 创建一个订阅者 将Block保存到订阅者中 , 将订阅者保存到上面的数组中
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    //3.发送信号 遍历信号对象中的数组,取出订阅对象! 调用订阅对象中的Block 执行!!
    [subject sendNext:@"dyz"];
基本使用二
    //1:创建信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        //3:发送信号
        [subscriber sendNext:@"dyz"];
        [subscriber sendCompleted];//RAC中不加这一句也可以 销毁,但是在RxSwift中必须加上这句,否则 无法销毁

        //4:销毁信号
        return [RACDisposable disposableWithBlock:^{
            NSLog(@"销毁了");
        }];
    }];

    //2:订阅信号。只有订阅了信号,才会激活信号
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    
    //3:发送信号
    
    //4:销毁信号
监听方法
    [[self.dYZView rac_signalForSelector:@selector(send:)] subscribeNext:^(RACTuple * _Nullable x) {
        NSLog(@"监听到了!!%@",x);
        RACTuple *tuple = x;
        NSLog(@"%@",tuple.first);//haha!!
    }];

#import "DYZView.h"
@implementation DYZView
-(IBAction)btnClick:(id)sender{
    [self send:@"haha!!"];
}
-(void)send:(id)objc{
    
}
@end
    [[self rac_signalForSelector:@selector(viewWillAppear:)] subscribeNext:^(RACTuple * _Nullable x) {
        
    }];
监听代理
    [[self rac_signalForSelector:@selector(textFieldDidBeginEditing:) fromProtocol:@protocol(UITextFieldDelegate)] subscribeNext:^(RACTuple * _Nullable x) {
        
        NSLog(@"%@",x);
    }];
    
    self.textField.delegate = self;
KVO
    //KVO
//    [self.hkView rac_observeKeyPath:@"frame" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
//        NSLog(@"%@",value);
//    }];
    
    [[self.hkView rac_valuesForKeyPath:@"frame" observer:nil] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

    self.person = [[Person alloc] init];
    self.person.car = @"car";
    // 这里已经有回调了所以 observer可以置为nil,随便写一个也可以,就写self吧
    [[self.person rac_valuesForKeyPath:@"car" observer:nil] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    //宏实现
    //1、
    [RACObserve(self.view, frame) subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

    //2、
    [RACObserve(self, name) subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    self.name = @"dyz";
监听事件
    //可以选择button Event类型
    [[self.btn rac_signalForControlEvents:(UIControlEventTouchUpInside)] subscribeNext:^(__kindof UIControl * _Nullable x) {
        NSLog(@"%@",x);
    }];
    //默认是UIControlEventTouchUpInside类型
    self.button.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {

        NSLog(@"%@",input);
        return [RACSignal empty];
    }];
通知
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"%@",x);
    }];//object 传字符串 不行ser
textFiled
    [_textFiled.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@",x);
    }];

    // 加skip 解决最开始开一次
    [[self.textField.rac_textSignal skip:1] subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@",x);
    }];
    //宏实现
    //用来给某个对象的某个属性绑定信号,只要产生信号内容,就会将内容赋值给属性!!
    RAC(_label,text)=_textField.rac_textSignal;
定时器
    //1、
    [[RACSignal interval:1.0 onScheduler:[RACScheduler scheduler]] subscribeNext:^(NSDate * _Nullable x) {
        NSLog(@"%@",[NSThread currentThread]);//子线程 滑动UI不会卡顿
    }];

    //2、
    [[RACSignal interval:1 onScheduler:[RACScheduler schedulerWithPriority:(RACSchedulerPriorityHigh) name:@"com.ReactiveCocoa.RACScheduler.mainThreadScheduler"]] subscribeNext:^(NSDate * _Nullable x) {       
        NSLog(@"%@",[NSThread currentThread]);
    }];
手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
    self.label.userInteractionEnabled = YES;
    [self.label addGestureRecognizer:tap];

    [tap.rac_gestureSignal subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {

        NSLog(@"%@",x);
    }];
数组 字典遍历
    NSArray *array = @[@"dyz",@"123",@"18"];
    [array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
       
        NSLog(@"%@",x);
    }];
    
    NSDictionary *dict = @{@"key":@"dyz",@"age":@"18",@"gender":@"1"};
    [dict.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
        //元祖
        NSLog(@"%@",x);
        RACTwoTuple *tuple = (RACTwoTuple *)x;
        NSLog(@"key == %@ , value = %@",tuple[0],tuple[1]);
    }];
循环引用
#import "ViewController.h"
#import <ReactiveObjC.h>

@interface ViewController ()

@property(nonatomic,strong)RACSignal * signal;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    @weakify(self);
    
    RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        @strongify(self);
        
        NSLog(@"%@",self);
        
        return nil;
    }];
    _signal = signal;
}
- (IBAction)dismiss:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)dealloc
{
    NSLog(@"成功的走了!!");
}
映射 flattenMap
    // flattenMap作用:把源信号的内容映射成一个新的信号,信号可以是任意类型。
    
    // flattenMap使用步骤:
    // 1.传入一个block,block类型是返回值RACStream,参数value
    // 2.参数value就是源信号的内容,拿到源信号的内容做处理
    // 3.包装成RACReturnSignal信号,返回出去。
    
    // flattenMap底层实现:
    // 0.flattenMap内部调用bind方法实现的,flattenMap中block的返回值,会作为bind中bindBlock的返回值。
    // 1.当订阅绑定信号,就会生成bindBlock。
    // 2.当源信号发送内容,就会调用bindBlock(value, *stop)
    // 3.调用bindBlock,内部就会调用flattenMap的block,flattenMap的block作用:就是把处理好的数据包装成信号。
    // 4.返回的信号最终会作为bindBlock中的返回信号,当做bindBlock的返回信号。
    // 5.订阅bindBlock的返回信号,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来。
    [[self.textField.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
        NSLog(@"处理:%@",value);
        return [RACReturnSignal return:[NSString stringWithFormat:@"dyz:%@",value]];//#import <RACReturnSignal.h>
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"逻辑处理:%@",x);
    }];
map
  • map 和 flattenMap的效果相似
    [[self.textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        NSLog(@"处理:%@",value);
        return [NSString stringWithFormat:@"dyz:%@",value];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"逻辑处理:%@",x);
    }];
过滤 filter
    [[self.textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
        
        if (self.textField.text.length > 6) {
            self.textField.text = [self.textField.text substringToIndex:6];
            return NO;
        } else {
            return YES;//返回为YES时,才会走到下面
        }
    }] subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"--%@++",x);
    }];
bind
    // 方式二:在返回结果前,拼接,使用RAC中bind方法做处理。
    // bind方法参数:需要传入一个返回值是RACStreamBindBlock的block参数
    // RACStreamBindBlock是一个block的类型,返回值是信号,参数(value,stop),因此参数的block返回值也是一个block。
    // RACStreamBindBlock:
    // 参数一(value):表示接收到信号的原始值,还没做处理
    // 参数二(*stop):用来控制绑定Block,如果*stop = yes,那么就会结束绑定。
    // 返回值:信号,做好处理,在通过这个信号返回出去,一般使用RACReturnSignal,需要手动导入头文件RACReturnSignal.h。
    
    // bind方法使用步骤:
    // 1.传入一个返回值RACStreamBindBlock的block。
    // 2.描述一个RACStreamBindBlock类型的bindBlock作为block的返回值。
    // 3.描述一个返回结果的信号,作为bindBlock的返回值。
    
    // 注意:在bindBlock中做信号结果的处理。
    // 底层实现:
    // 1.源信号调用bind,会重新创建一个绑定信号。
    // 2.当绑定信号被订阅,就会调用绑定信号中的didSubscribe,生成一个bindingBlock。
    // 3.当源信号有内容发出,就会把内容传递到bindingBlock处理,调用bindingBlock(value,stop)
    // 4.调用bindingBlock(value,stop),会返回一个内容处理完成的信号(RACReturnSignal)。
    // 5.订阅RACReturnSignal,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来。
    
    // 注意:不同订阅者,保存不同的nextBlock,看源码的时候,一定要看清楚订阅者是哪个。
    // 这里需要手动导入#import <ReactiveCocoa/RACReturnSignal.h>,才能使用RACReturnSignal。
    [[self.textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{

        return ^RACSignal * (id _Nullable value, BOOL *stop) {

            return [RACReturnSignal return:[NSString stringWithFormat:@"输出:%@",value]];
        };

    }] subscribeNext:^(id  _Nullable x) {

        NSLog(@"subscribeNext == %@",x);
    }];
组合 combineLatest

两个信号都执行过之后,才会触发,不存在什么记忆

    RACSignal *signalA = self.textField.rac_textSignal;
    RACSignal *signalB = [self.button rac_signalForControlEvents:UIControlEventTouchUpInside];
    RACSignal *comSig = [signalA combineLatestWith:signalB];
    [comSig subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
    RACSignal *signalA = self.textField.rac_textSignal;
    RACSignal *signalB = [self.button rac_signalForControlEvents:UIControlEventTouchUpInside];
    RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id _Nonnull(id value1,id value2){//value1和value2 的类型 必须是 OC类型
       
        return [NSString stringWithFormat:@"reduce == %@ ++ %@",value1,value2];//返回的类型也必须是OC类型
    }];
    [reduceSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"subscribeNext == %@",x);
    }];
}
contact
    RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"dyz"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"iOS"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    RACSignal *contactSignal = [signalA concat:signalB];
    
    [contactSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"==%@++",x);
    }];

2020-08-06 17:16:35.429844+0800 DemoOC[13105:3549275] ==dyz++
2020-08-06 17:16:35.430114+0800 DemoOC[13105:3549275] ==iOS++
then
    RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"dyz"];
        [subscriber sendCompleted];
        return nil;
    }];

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

    RACSignal *sigThen = [signalA then:^RACSignal * _Nonnull{

        return signalB;
    }];
    [sigThen subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

2020-08-06 17:27:59.940039+0800 DemoOC[13324:3560206] iOS
merge
    // merge:把多个信号合并成一个信号
    //创建多个信号
    RACSignal *signalA = [self.textField.rac_textSignal skip:1];
    RACSignal *signalB = [self.button rac_signalForControlEvents:UIControlEventTouchUpInside];
    
    // 合并信号,任何一个信号发送数据,都能监听到.
    RACSignal *mergeSignal = [signalA merge:signalB];
    
    [mergeSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"++%@=",x);
    }];
zip
    //signalA 和 signalB 都触发了,才能监听到。并且会一一对应,就是signalA的第二次触发会对应signalB的第二次触发,signalA的第三次触发会对应signalB的第三次触发。相当于有个记忆的能力。
    RACSignal *signalA = [self.textField.rac_textSignal skip:1];
    RACSignal *signalB = [self.button rac_signalForControlEvents:UIControlEventTouchUpInside];
    RACSignal *signalZip = [signalA zipWith:signalB];
    [signalZip subscribeNext:^(id  _Nullable x) {
        NSLog(@"++%@=",x);
    }];
Ignore
distinctUntilChanged
    // 当上一次的值和当前的值有明显的变化就会发出信号,否则会被忽略掉。
    //在开发中,刷新UI经常使用,只有两次数据不一样才需要刷新
    RACSubject *subject = [RACSubject subject];
    [[subject distinctUntilChanged] subscribeNext:^(id  _Nullable x) {
        NSLog(@"++%@=",x);
    }];
    // 发送信号
    [subject sendNext:@"1"];
    [subject sendNext:@"2"];
    [subject sendNext:@"2"];
skip
    //表示输入第一次,不会被监听到,跳过第一次发出的信号
    [[self.textField.rac_textSignal skip:1] subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"++%@=",x);
    }];
    
    [[[self.button rac_signalForControlEvents:UIControlEventTouchUpInside] skip:1] subscribeNext:^(__kindof UIControl * _Nullable x) {
        NSLog(@"++%@=",x);
    }];
take
    // take:可以屏蔽一些值,取前面几个值---这里take为2 则只拿到前两个值
    RACSubject *subject = [RACSubject subject];
    [[subject take:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"==%@+",x);
    }];
    // 发送信号
    [subject sendNext:@"111"];
    [subject sendNext:@"112"];
    [subject sendNext:@"113"];
takeLast
    //takeLast:和take的用法一样,不过他取的是最后的几个值,如下,则取的是最后两个值
    //注意点:takeLast 一定要调用sendCompleted,告诉他发送完成了,这样才能取到最后的几个值
    RACSubject *subject = [RACSubject subject];
    [[subject takeLast:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"++%@=",x);
    }];
    [subject sendNext:@"111"];
    [subject sendNext:@"112"];
    [subject sendNext:@"113"];
    [subject sendCompleted];
takeUntil
    // takeUntil:---给takeUntil传的是哪个信号,那么当这个信号发送信号或sendCompleted,就不能再接受源信号的内容了。
    RACSubject *subjectA = [RACSubject subject];
    RACSubject *subjectB = [RACSubject subject];
    [[subjectA takeUntil:subjectB] subscribeNext:^(id  _Nullable x) {
        NSLog(@"==%@+",x);
    }];
    [subjectA sendNext:@"1"];
    [subjectA sendNext:@"2"];
//    [subjectB sendNext:@"3"];
    [subjectB sendCompleted];
    [subjectA sendNext:@"4"];
switchToLatest
    RACSubject *signalOfSignals = [RACSubject subject];
    RACSubject *signal = [RACSubject subject];
    // 获取信号中信号最近发出信号,订阅最近发出的信号。
    // 注意switchToLatest:只能用于信号中的信号
    [signalOfSignals.switchToLatest subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    [signalOfSignals sendNext:signal];
    [signal sendNext:@1];
    [signal sendNext:@"123"];
timeout
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        return nil;
    }] timeout:1 onScheduler:[RACScheduler scheduler]];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    } error:^(NSError * _Nullable error) {
        NSLog(@"%@",error);
    }];

replay
retry

相关文章

网友评论

      本文标题:ReactiveObjC(一)

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