ReactiveCocoa RAC 响应式函数编程(FRP)

来源:互联网 发布:ipad pro实用软件 编辑:程序博客网 时间:2024/04/30 10:25

RACSignal

 /**     *  手动创建信号     *     *  其中的:RACDisposable 当调用  [subscriber sendCompleted]或者[subscriber sendError:nil] 自动调用 可以返回nil     *     */    RACSignal *signal=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {        [subscriber sendNext:@"signal send next"];        [subscriber sendCompleted];        //[subscriber sendError:nil];        return [RACDisposable disposableWithBlock:^{            NSLog(@"signal 发送完成销毁");        }];    }];    /**     *  给信号添加订阅者     *     *  @param x 调用订阅者的 [subscriber sendNext:@"signal send next"]  subscribeNext 中传的就是sendNext传递的value     *        *     *  @return RACDisposable 可用于手动调用销毁信号     */    RACDisposable *disposal= [signal subscribeNext:^(id x) {        NSLog(@"signal 给订阅者发送信号:%@",x);    } error:^(NSError *error) {         NSLog(@"signal 发生错误");    }];    //[disposal dispose];    [[self rac_signalForSelector:@selector(test)] subscribeNext:^(id x) {        NSLog(@"test 调用");//执行了test 方法后调用next    }];

事件,KVO,通知等

 // @weakify(self) 避免循环引用    @weakify(self);    /**     *  监听文本的输入     *     *  @param x TextFiled 的text 类型为id 可以直接修改NSString     *     *  @return     */    [[self.mTextFiled1 rac_textSignal] subscribeNext:^(NSString *value) {        NSLog(@"文本1:%@",value);    }];    /**     *  监听按钮点击     *     *  @param x value 为按钮本身     *     *  @return     */    [[self.mButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *button) {        button.backgroundColor=[UIColor yellowColor];        NSLog(@"点击了按钮");    }];    /**     *  kvo     *     *  @param self.person target     *  @param name         keypath     *  skip:1  忽略第一次name的信号,name 第一次为nil 也会发出信号     *  @return     */    [[RACObserve(self.person, name)  skip:1]subscribeNext:^(NSString *value) {        @strongify(self);        [self.mButton setTitle:value forState:UIControlStateNormal];    }];    /**     *  RAC(target,property)=信号     *  RAC 宏 target.property=信号的subscribeNext 传递的值     */    RAC(self.person,name)=self.mTextFiled1.rac_textSignal;    /**     *  通知     *     *  @param x 通知     *     *  @return     *  takeUntil 取消订阅的信号 self.rac_willDeallocSignal 当前self即将销毁的时候会取消订阅     */    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {        NSLog(@"通知%@",x);    }];    /*     * 代理:创建 =[[RACDelegateProxy alloc] initWithProtocol:@protocol(协议名称)]     * 成为代理:vc.delegate=(id<ToViewControllerDelegate>)self.proxy; 强制类型转换即可     */    self.proxy=[[RACDelegateProxy alloc] initWithProtocol:@protocol(ToViewControllerDelegate)];    [[self.proxy signalForSelector:@selector(toViewControllerAction:p2:)] subscribeNext:^(RACTuple *value) {        /**         *  元组解包         *  p1=value.first p2.value.second         */        RACTupleUnpack(NSString *p1,NSString *p2)=value;        NSLog(@"ToViewControllerDelegate 的 toViewControllerAction 方法执行了 参数1%@ 参数2:%@",p1,value.second);    }];

RACSuject

 /**     *  RACSubject 本身就是信号,同时自己发送信号 调用sendNext 其他订阅者可以接收到信号     *  RACSubject 创建本身不需要block      *  RACSubject 常用于代理     */    RACSubject *racSuject=[RACSubject subject];    [racSuject subscribeNext:^(id x) {        NSLog(@"订阅1");    }];    [racSuject subscribeNext:^(id x) {        NSLog(@"订阅2");    }];    [racSuject sendNext:racSuject];    ToViewController *vc=[ToViewController new];    //创建代理    vc.signalDelegate=[RACSubject subject];    //订阅    [vc.signalDelegate subscribeNext:^(RACTuple *value) {        /**         *  第一个参数设置为int类型 假设多个代理方法的时候,就可以用这种方法去处理代理的不同方法 可以将这个参数设置为常量         */        switch ([value.first integerValue]) {            case 1:                NSLog(@"执行代理方法 参数1:%@ 参数2:%@",value.second,value.third);                break;            default:                break;        }    }];    [self.navigationController pushViewController:vc animated:YES];

RACReplaySubject

 /**     *  RACReplaySubject 可以先发送信号,在订阅 RACSubject 不可以     *  RACReplaySubject 先将value 保存起来 有新的订阅者就会将之前的所有的value重新发送一遍     *  RACSubject 保存的订阅者,有新的者,遍历订阅者一个个发送     */    RACReplaySubject *replaySubject=[RACReplaySubject subject];    [replaySubject sendNext:@"1"];    [replaySubject sendNext:@"2"];    [replaySubject subscribeNext:^(id x) {        NSLog(@"订阅者1 接收的value:%@",x);    }];    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        [replaySubject subscribeNext:^(id x) {            NSLog(@"订阅者2 接收的value:%@",x);        }];    });

RACSequence

 /**     *     * RACSequence :集合     * 1.集合转换为集合信号RACSequence rac_sequence     * 2.订阅信号中的信号 rac_sequence.signal     */    NSArray *array=@[@1,@2,@3,@4];    [array.rac_sequence.signal subscribeNext:^(id x) {        NSLog(@"遍历数组%@",x);    }];    NSDictionary *dict=@{@"key1":@1,@"key2":@2};    [dict.rac_sequence.signal subscribeNext:^(RACTuple *value) {        NSLog(@"遍历字典 key:%@ value:%@",value.first,value.second);    }];

RACCommand

/**     *  RACCommand 命令 多用于网络请求,因为它可以监听sinal的请求状态     *     */    RACCommand *racCommand=[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {        NSLog(@"start command");        //return [RACSignal empty]; 必须返回信号,不可以返回nil        return  [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{                [subscriber sendNext:@"下载的数据"];                [subscriber sendCompleted];            });            return nil;        }];    }];    /**     *  强引用,不然会被销毁     */    _racCommand=racCommand;    /**     *  executionSignals 获取命令中执行返回的信号     */    [_racCommand.executionSignals subscribeNext:^(id x) {       [x subscribeNext:^(id x) {           NSLog(@"订阅1 请求数据 %@",x);       }];    }];    /*     _racCommand.executionSignals.switchToLatest 获取最后一个信号 常用获取命令中的信号     */    [_racCommand.executionSignals.switchToLatest subscribeNext:^(id x) {            NSLog(@"订阅2 请求的数据%@",x);    }];    [[_racCommand.executing skip:1] subscribeNext:^(id x) {        if([x boolValue]){            NSLog(@"命令正在执行过程中");        }else{            NSLog(@"命令完成");        }    }];    //执行命令    [self.racCommand execute:@1];

信号绑定

@weakify(self);    [[self.mTextFiled1.rac_textSignal bind:^RACStreamBindBlock{        /*         * 当原信号发出的时候,就会执行以下block         * block 处理原来的信号         * 返回新的信号 RACReturnSignal 需要导入<ReactiveCocoa/RACReturnSignal.h>         * (id value,BOOL *stop) value 为原信号的value stop=yes 就会结束绑定         *         */        return ^RACStream *(id value,BOOL *stop){            *stop=self.stop;            NSLog(@"处理绑定的信号");            return [RACReturnSignal return:[NSString stringWithFormat:@"bind%@",value]];        };    }] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        NSLog(@"取消了绑定");        self.stop=YES;//2 秒后取消绑定,但是还是会执行一次,因为执行一次后,才会重新赋值为Yes,取消绑定    });

映射

/**     原理绑定     如果信号发出的值不是信号,映射一般使用Map 发出的值是信号 flattenMap     */    @weakify(self);    [[self.mTextFiled1.rac_textSignal flattenMap:^RACStream *(id value) {        NSLog(@"处理绑定的信号");        return [RACReturnSignal return:[NSString stringWithFormat:@"bind%@",value]];    }] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];    /*     * 同样还是绑定 常用于修改原信号的返回值,返回自己想要的值     */    [[self.mTestField2.rac_textSignal map:^id(id value) {        return [NSString stringWithFormat:@"bind2%@",value];    }] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];

过滤等

@weakify(self);    /*     * filter返回Yes 的信号才会往下传递     */    [[self.mTextFiled1.rac_textSignal filter:^BOOL(NSString *value) {        return [value isEqualToString:@"filter"];    }] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];    /*     *忽略ignore的value 例如以下123 不会发出信号     */    [[self.mTestField2.rac_textSignal ignore:@"123"] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];    //distinctUntilChanged 当上次一次信号的值和新的一次的值不一样的时候才会发出信号,常用于UI的刷新    [[self.mTestField2.rac_textSignal  distinctUntilChanged] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];    /*     * take :次数  发出限定次数后不在订阅 以下的方法实际只会看到textFiled输入一次后就不会改变了,默认执行1次,textfiled获取焦点执行一次,输入执行一次     */    [[self.mTextFiled1.rac_textSignal take:3] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];    /**     * takeLast 只取最后n次,但是前提是sendCompleted 就是必须知道这个信号发出几次后才能确定最后n次信号,是那几个信号     * 还有skip 跳过前 n次信号   switchToLatest 取最后一次信号发送,同样需要调用 sendCompleted     */    RACSubject *subject=[RACSubject subject];    [[subject takeLast:1] subscribeNext:^(id x) {        @strongify(self);        [self.mButton setTitle:x forState:UIControlStateNormal];    }];    /**     *   发送信号必须在订阅之后     */    [subject sendNext:@"1"];    [subject sendNext:@"2"];    [subject sendNext:@"3"];    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        [subject sendCompleted];    });

连接

 /*     *     *concat 信号源1 连接 信号源2  信号1调用completed才会执行发送信号2     *可以使用then连接,原理是concat,concat实际是过滤信号2的发出的信号,当信号1结束只会才会执行信号源2发送的信号     * merge 合并信号(或|合并)只要有个信号源发出信号,就会执行订阅者的block     * zipWith: 合并信号(且|合并) 两个信号同时发出才会执行,value是一个元组     */    RACSignal *signal1=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {        [subscriber sendNext:@"1"];        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{            [subscriber sendCompleted];        });        return nil;    }];    RACSignal *singal2=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {        [subscriber sendNext:@"2"];        return nil;    }];    RACSignal *connect=[signal1 concat:singal2];    [connect subscribeNext:^(id value) {        NSLog(@"接受到信号%@",value);    }];

合并

 /*     * comLast 合并最新的信号 reduce 聚合     */    RACSignal *signal=[RACSignal combineLatest:   @[    [ self.mTextFiled1.rac_textSignal filter:^BOOL(NSString *value) {        return value.length>2;    }],    [self.mTestField2.rac_textSignal filter:^BOOL(NSString *value) {        return value.length>2;    }]    ]    reduce:^id(NSString *v1,NSString *v2){//默认空参数,可以手动添加       return [NSString stringWithFormat:@"%@-%@",v1,v2];    }];    RAC(self.mButton,backgroundColor)=[signal map:^id(NSString  *value) {        NSLog(@"%@",value);        return [value isEqualToString:@"123-123456"]?[UIColor blackColor]:[UIColor redColor];    }];

Time相关

   /*    * timeout: 2  2后自动调用 error    */  [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {      return nil;  }] timeout:2 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {      NSLog(@"1.timeout next");  } error:^(NSError *error) {      //两秒后自定调用error      NSLog(@"1.timeout error");  }];    /*    delay:2 2秒执行block     */    [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {        [subscriber sendNext:@"2"];        return nil;    }] delay:2] subscribeNext:^(id x) {        NSLog(@"2s: %@",x);    }];    static int i=0;    /*     retry 只要sendError 就会重新执行一次block 直到成功     */    [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {        if(i>5){            [subscriber sendNext:@"2"];            [subscriber sendCompleted];            NSLog(@"next i:%d",i);        }else{            [subscriber sendError:nil];            NSLog(@"error i:%d",i);            i++;        }        return nil;    }] retry] subscribeNext:^(id x) {        NSLog(@"---data:%@",x);    }];
0 0
原创粉丝点击