函数式响应式编程框架ReactiveCocoa总结

前端之家收集整理的这篇文章主要介绍了函数式响应式编程框架ReactiveCocoa总结前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

ReactiveCocoa与函数响应式编程
在Cocoa框架下的的函数响应式编程框架。Github mac客户端产物,富含cocoa框架多种组件,提供基于时间变化的数据流的组合和变换。@H_502_4@

命令式编程vs函数式响应式编程
命令式编程用语言提供的操作命令编写操作序列给电脑执行。
函数式编程:将电脑的运算视为函数的运算,包含如下特性:
闭包和高阶函数函数可以作为对象,作为参数输入和作为结果返回
惰性计算:表达式值不需要绑定的时候计算,在求值程序需要产生表达式的值时进行计算。
递归:通过递归,避免定义状态变量。
修改状态:不改变系统的外部状态,内部不定义状态变量
没有副作用:副作用指修改系统的状态,影响其它模块,函数式编程都是表达式语句,不包含任何赋值语句,变量值一 旦被指派,就永远不会改变
和命令式编程相比,函数式编程由表达式组成,内部不含状态变化,内部不含有变量,通过递归解决问题。
函数式编程好处:
1. 代码简洁,开发快速
2. 接近自然语言,易于理解
3. 代码方便管理
4. 易于”并发编程”
5. 代码的热升级
响应式编程:一种面向数据流和变化传播的编程范式,对象和对象之间的相互影响,一个对象变化关联的对象会跟着变化。一个变化抽象为一种信号,产生数据流变化。
1.对信号产生的数据流值的操作
2.信号产生的数据流的数量操作
3.信号产生的数据流的纬度操作
4.信号产生的数据流的合并处理@H_502_4@

ReactiveCocoa使用@H_502_4@

//target--action
    [[textField rac_textSignal] subscribeNext:^(UITextField *textField) {
        NSLog(@"%@",textField);
    }];
    [[textField rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(UITextField *field) {
        NSLog(@"%@",field.text);
    }];

    //notification
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"111" object:nil] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"111" object:@"111"];

    //kvo
    [RACObserve(self,title) subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    self.title = @"xxxx";
    //delegate
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"gogogo" message:@"gogogo" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:nil];
    [[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple *tuple) {
        NSLog(@"%@",tuple.first);
        NSLog(@"%@",tuple.second);
        NSLog(@"%@",tuple.third);
    }];
    [alertView show];

    //冷信号 创建信号 发送信号 订阅信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"发送值"];
        return [RACScopedDisposable disposableWithBlock:^{
            NSLog(@"被销毁");
        }];
    }];
    [signal subscribeNext:^(id x) {
        NSLog(@"接受到信号的值");
    }];

    //热信号 创建 订阅 发送信号
    RACSubject *subject = [RACSubject subject];
    [subject subscribeNext:^(id x) {
        NSLog(@"收到发送的信号");
    }];
    [subject subscribeNext:^(id x) {
        NSLog(@"收到发送的信号");
    }];
    [subject sendNext:@"11111"];

    //元组 遍历 效率太差 慎用
    NSArray *array = @[@"123",@"1234",@"2356"];
    [array.rac_sequence.signal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

    //RACCOMMAND
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            [subscriber sendNext:@"hhahahahah"];
            return [RACDisposable disposableWithBlock:^{

            }];
        }];
        return signal;
    }];
    [command execute:@"111"];

    //Racmuticastconnection
    RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"hhahahahah"];
        return [RACDisposable disposableWithBlock:^{
            NSLog(@"-----");
        }];

    }];
    RACMulticastConnection *connection = [signalA publish];
    [connection.signal subscribeNext:^(id x) {
        NSLog(@"----------------x");
    }];
    [connection.signal subscribeNext:^(id x) {
        NSLog(@"-----------------x");
    }];
    [connection connect];

    //常用的宏定义
    [[RACObserve(self,title) replayLazily] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    //绑定
    RAC(self,title) = [textField.rac_textSignal replayLazily];
    [textField.rac_textSignal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

    [[[textField rac_textSignal] bind:^RACStreamBindBlock{
        return ^RACStream *(id value,BOOL *stop) {
            return [RACReturnSignal return:[NSString stringWithFormat:@"输出:%@",value]];
        };
    }] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    //MAP
    [[textField.rac_textSignal map:^id(id value) {
        return [NSString stringWithFormat:@"11111%@",value];
    }] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    /// faltenmap
    [[textField.rac_textSignal flattenMap:^RACStream *(id value) {
        return [RACReturnSignal return:value];
    }] subscribeNext:^(id x) {
        NSLog(@"dsdddd%@",x);
    }];
    //contact 先发送信号a ,型号a发送完成 才发送 signal
    RACSignal *signacContact = [signalA concat: signal];
    [signacContact subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    //merge 多个信号合并为一个信号,任何一个信号有新值都会调用
    RACSignal *signacMerge = [signalA merge:signal];
    [signacMerge subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    //zipwith 合并两个信号,并把两个信号内容合并为元组
    RACSignal *zipSignal = [signalA zipWith:signal];
    [zipSignal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

    //过滤
    [textField.rac_textSignal filter:^BOOL(NSString *value) {
        return value.length > 3;
    }];
    [textField.rac_textSignal ignore:@"3"];
    [[textField.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {

    }];
    [[textField.rac_textSignal skip:3] subscribeNext:^(id x) {

    }];
    [[textField.rac_textSignal takeLast:3] subscribeNext:^(id x) {

    }];
    [textField.rac_textSignal takeUntil:signal];

    //秩序
    [[textField.rac_textSignal doNext:^(id x) {

    }] doCompleted:^{

    }];
    //多线程 racSchedule
    [[RACScheduler scheduler] afterDelay:0 schedule:^(void) {

    }];
    [[signal deliverOn:[RACScheduler scheduler]] subscribeNext:^(id x) {

    }];
    [signal subscribeOn:[RACScheduler scheduler]];
    //时间 timeout delay interval
    [textField.rac_textSignal timeout:0.01 onScheduler:[RACScheduler currentScheduler]];
    [textField.rac_textSignal delay:1.0];
    [textField.rac_textSignal subscribeError:^(NSError *error) {
        NSLog(@"error");
    }];
    [[RACSignal interval:1 onScheduler:[RACScheduler scheduler]] subscribeNext:^(id x) {
        NSLog(@"FDF");
    }];
    //RAC之重复 replay replaylazily
    RACSignal *signal_replay = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"1111"];
        return nil;
    }] replayLazily];
    [signal_replay subscribeNext:^(id x) {
        NSLog(@"11111");
    }];
    [signal_replay subscribeNext:^(id x) {
        NSLog(@"11111");
    }];
    //replaylast
    RACSubject *subjectaaa = [RACSubject subject];
    RACSignal *signalaaaaa = [subjectaaa replayLast];
    [subjectaaa sendNext:@"1111"];
    [subjectaaa sendNext:@"33333"];
    [signalaaaaa subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    [subjectaaa sendNext:@"333"];
    [signalaaaaa subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    @weakify(self)
    [subjectaaa subscribeNext:^(id x) {
        @strongify(self);
    }];

踩坑总结@H_502_4@

//1.RACObserve 带来的循环引用
    [subjectaaa subscribeNext:^(id x) {
        @strongify(self)
        RACObserve(self,title);
    }];
    //RACSubject 进行了 map、filter、merge、combineLatest、flattenMap转换操作后,要发送complete ,不然无法释放
    [[subjectaaa map:^id(NSNumber *value) {
        return @([value integerValue] *3);
    }] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    [subjectaaa sendNext:@(123)];
    [subjectaaa sendCompleted];
    //signal造成的多次订阅问题,使用reply,replayLazily让subscriber里面的代码只被执行一次

小结
RACCommand作用
重复执行一个过程
开关控制
防止重入
结果统一处理@H_502_4@

属性
executionSignals 所有的执行信号,使用switchToLatest(获取信号中的信号)降阶
excuting 是否正在执行command
enabled 开关信号
errors 所有的错误信号,对错误进行统一处理
allowsConcurrentExecution 是否支持并发执行@H_502_4@

Racchannel 本质是一个signal
双向通话
处理回声问题@H_502_4@

RAC宏 : 将信号产生的值和rac括号内的值绑定
RAC(self.outputLabel,text) = self.inputTextField.rac_textSignal;
重复绑定抛出异常
takeuntil 取消绑定@H_502_4@

什么场景使用rac
1.异步场景 (处理成功 失败 错误 变换和组合 串联 错误传递和捕获 线程处理)
2.响应事件处理(ui时间 delegate)
3.切面处理(方法调用监听)@H_502_4@

副作用消除
在doNext中显式声明
只有订阅才产生副作用
保证信号变换返回新的不改变旧的@H_502_4@

frp思维
需求分析
输入 输出
数据流图@H_502_4@

小技巧
instruments RAC instruments文件添加调试规则到instruments (主要是通过对rac的理解来解决问题)
nsmutableArray 通过mutableArrayForKey来取得值 监听add remove方法
错误处理:使用raccommand统一处理 catch 转发至subject
RAC是函数响应式编程框架,不是专门为mvvm提供绑定的工具。
demo@H_502_4@

猜你在找的React相关文章