美文网首页
读书笔记

读书笔记

作者: konglei | 来源:发表于2018-02-06 17:05 被阅读8次

读 顾语流年 RAC+MVVM的项目实例演练 项目有感

向作者说的再写项目之前先想好架构,将一些东西封装进基类是比较省事省力的方法

M很正常

V controller中的view做了解耦使用rac将逻辑放到了vc的ViewModel中,比如将tableView、collectionView绑定到VM,然后再VM中实现其代理方法 。再使用RACSubject做了一些方法的回调(页面跳转逻辑)到Controller中。 但是cell(tableViewCell、collectionViewCell)的逻辑没有做分离,还是存在于cell中,只是使用RAC做了赋值操作、回调操作(向ViewModel逆向传值 代理方法写在VM中)

C controller负责做view的加载、接口的调用时机、将view绑定到ViewModel中 还有具体的跳转代码写在C中

VM 在一个VC中可以根据不同的业务持有多个VM,不同的数据请求也可以在不同的VM中直接请求。 直接在VM中请求接口,同时做了模型转换 直接持有了M 

RACCommand 负责数据请求

RACSubject 负责逻辑操作:赋值操作、页面跳转操作、逆向值传递、点击事件的操作

对已赋值操作可以使用宏进行信号绑定

RAC(self.label, text) =self.textField.rac_textSignal;

GOOG Code

//获取首页列表数据

- (void)requestHomeListInfo {

    @weakify(self);

    _homeListCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {

        @strongify(self);

        if(!self.firstLoadData) {

            return[RACSignalempty];

        }

        RACSignal*requestSignal = [RACSignalcreateSignal:^RACDisposable*(id subscriber) {

            [[WLNetworkToolsharedInstance]loadHomeListData:[inputintValue]success:^(idresponse) {

                self.firstLoadData=NO;

                [subscribersendNext:response];

                [subscribersendCompleted];

            }failure:^(NSError*error) {

                [subscribersendError:error];

                [subscribersendCompleted];

            }];

            returnnil;

        }];

        return[requestSignalmap:^id(NSDictionary*value) {

            NSArray*data = value[@"data"][@"items"];

            NSArray*modelsArray = [[data.rac_sequencemap:^id(idvalue) {

                return[WLHomeListModelmj_objectWithKeyValues:value];

            }]array];

            //这一步刷新列表可以放到这里,也可以放到控制器里面

            NSLog(@"请求首页列表数据成功 %@",modelsArray);

            if(modelsArray && modelsArray.count>0) {

                [self.homeListArrayremoveAllObjects];

                [self.homeListArrayaddObjectsFromArray:modelsArray];

                [self.tableViewreloadData];

            }

            returnmodelsArray;

        }];

    }];

}

后记

//    RACSignal使用步骤

    /**

     *1.创建信号

     *2.订阅信号(订阅信号后,才会被激活)

     *3.发送信号

     /RACSignal底层实现

     1、创建信号,首先把didSubscribe保存到信号中,还不会触发

     2、当信号被订阅,也就是调用signal的subscribrNext:nextBlock, subscribeNext内部会创建订阅者subscriber,并把nextBlock保存到subscriber中,subscribNext内部会调用signal的didSubscribe

     3、signal的didsubcribe中调用【subscriber sendNext:@1】,sendNext底层其实就是执行subscriber的nextBlock。

     */

    //    1.创建信号

    RACSignal*signal  = [RACSignal createSignal:^RACDisposable *(id subscriber) {

        //        block调用时刻:每当有订阅者订阅信号,就会调用block

        //        2 发送信号

        [subscribersendNext:@1];

        NSLog(@"111-------------");

        //      如果不再发送数据,最好调用发送信号完成方法,内部会自动调用[RACDisposable disposable]

        [subscribersendCompleted];

        return [RACDisposable disposableWithBlock:^{

            NSLog(@"111信号被销毁");

        }];

    }];

    //    3.订阅信号,才会激活信号

    [signalsubscribeNext:^(idx) {

        NSLog(@"111接受到数据:%@",x);

    }];

    [signalsubscribeNext:^(idx) {

        NSLog(@"222jiehsoushuji---%@",x);

    }];

//    RACSubject使用步骤

/**

    1、创建信号 【RACSubject subject】,跟RACSignal不一样,创建信号时没有block。

    2、订阅信号 -(RACDisposable *)subscribeNext:(void(^)(id x)nextBlock)

    3、发送信号 sengNext:(id Value)

// RACSubject : 底层实现跟RACSignal不一样

    1、调用subscribeNext订阅信号,只是把订阅者保存起来,并且订阅者的nextBlock已经赋值了。

    2、调用sendNext发送信号,遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock

 */

//    1、创建信号

    RACSubject *subject = [RACSubject subject];

//    2、订阅信号

    [subjectsubscribeNext:^(idx) {

//        block调用时刻:当信号发出新值,就会调用

        NSLog(@"第一个订阅者:%@",x);

    }];

    [subjectsubscribeNext:^(idx) {

        NSLog(@"第二个订阅者:%@",x);

    }];

//    3、发送信号

    [subjectsendNext:@1];

    [subjectsendNext:@2];

//    RACRepalySubject使用步骤

/**

 1、创建信号 [RACReplaySubject subject] ,跟RACSignal不一样,创建信号时没有block

 2、可以先发送信号,再订阅信号,RACSubject不可以!!!

    *订阅信号 -(RACDisposable)subscribeNext:(void(^)(id x))nextBlock

    *发送信号 sendNext:(id)value

 RACReplaySubject:底层实现和RACSubject不一样

    1、调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock

    2、调用subscribeNext订阅信号,遍历所有保存的值,一个一个调用订阅者的nextBlock

 如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,再订阅信号

 也就是先保存值,再订阅值

*/

//    1、创建信号

    RACReplaySubject *replaySubject = [RACReplaySubject replaySubjectWithCapacity:2];

//    2、发送信号

    [replaySubjectsendNext:@1];

    [replaySubjectsendNext:@2];

//    3、订阅信号

    [replaySubjectsubscribeNext:^(idx) {

        NSLog(@"第一个订阅者收到的数据%@",x);

    }];

    [replaySubjectsubscribeNext:^(idx) {

        NSLog(@"第二个订阅者收到的数据%@",x);

    }];

/**

 // 先订阅,后发送信号

 2016-08-29 16:18:23.154 RACDemo[5507:185680] 第一个订阅者收到的数据1

 2016-08-29 16:18:23.154 RACDemo[5507:185680] 第二个订阅者收到的数据1

 2016-08-29 16:18:23.154 RACDemo[5507:185680] 第一个订阅者收到的数据2

 2016-08-29 16:18:23.155 RACDemo[5507:185680] 第二个订阅者收到的数据2

 */

/**

// 先发送信号,再订阅

 2016-08-29 16:19:43.945 RACDemo[5641:186739] 第一个订阅者收到的数据1

 2016-08-29 16:19:43.945 RACDemo[5641:186739] 第一个订阅者收到的数据2

 2016-08-29 16:19:43.946 RACDemo[5641:186739] 第二个订阅者收到的数据1

 2016-08-29 16:19:43.946 RACDemo[5641:186739] 第二个订阅者收到的数据2

 */

//    1、遍历数组

    NSArray*array =@[@1,@2,@3];

//    1、把数组转换成集合RACSequence,array.rac_seuqence

//    2、把集合RACSequence转换RACSignal信号类,array.rac_sequence.signal

//    3、订阅信号,激活信号,会自动把集合中的所有值,遍历出来

    [array.rac_sequence.signalsubscribeNext:^(idx) {

        NSLog(@"%@",x);

    }];

//    2、遍历字典,遍历出来的键值会包装成RACTuple(元祖对象)

    NSDictionary *dic = @{@"name":@"wangtongke",@"age":@18};

    [dic.rac_sequence.signal subscribeNext:^(id x) {

//        遍历字典  X为RAC的元祖(RACTuple)

//        解包元祖,会把元祖的值,按顺序给参数里边的变量赋值

        RACTupleUnpack(NSString *key,NSString *value) = x;

//        以上 相当于一下写法

//        NSString *key1 = x[0];

//        NSString *value1 = x[1];

        NSLog(@"%@  %@\n",key,value);

    }];

/**

 1、创建命令 initWithSignalblock:(RACSignal * (^)(id input))signalBlock

 2、在signalBlock中,创建RACSignal,并且作为signalBlock的返回值

 3、执行命令 -(RACSignal *)execute:(id)input

// 注意事项

 1、signalBlock必须要返回一个signal,不能返回nil,

 2、如果不想要传递信号,直接创建空的信号返回[RACSignal empty];

 3、RACCommand,如果数据传递完毕,必须调用[subscriber sendCompleted],这时命令才会执行完毕,否则永远处于执行中.

 4、RACComand需要被强引用,否则接手不到RACCommand中的信号,因此,RACCommand中的信号是延迟发送的。

// 设计思想  : 内部signalBlock为什么要返回一直信号,这个信号有什么用

 1、在RAC开发中,通常会把网络请求封装到RACCommand,直接执行某个RACCommand就能发送请求。

 2、当RACCommand内部请求到数据的时候,需要把请求的数据传递给外界,这时候就需要通过signalBlock返回的信号传递了

// 如何拿到RACCommand中返回信号发出的数据

 1、RACCommand有个执行信号源executionSignal,这个signal of signal(信号的信号),意思是发出的数据是信号,不是普通的类型

 2、订阅executionSignal就能拿到RACCommand中返回的信号,然后订阅signalblock返回的信号。

// 监听当前命令是否正在执行executing

// 使用场景  按钮点击,网络请求

 */

//  *******  1、创建命令

    RACCommand*command = [[RACCommandalloc]initWithSignalBlock:^RACSignal*(idinput) {

        NSLog(@"执行命令");

        NSLog(@"input---%@",input);

//        创建空信号,必须返回信号

//        return [RACSignal empty];

//  *******  2、创建信号,用来传递数据

        return [RACSignal createSignal:^RACDisposable *(id subscriber) {

            [subscribersendNext:@"请求数据"];

//            注意:数据传递完,最好调用sendCompleted,这时命令才执行完毕

            [subscribersendCompleted];

            return [RACDisposable disposableWithBlock:^{

            }];

        }];

    }];

//    强引用命令,不然会自动销毁,接受不到数据

    _command    = command;

//  *******  3、订阅RACCommand中的信号

    [command.executionSignalssubscribeNext:^(idx) {

        [xsubscribeNext:^(idx) {

            NSLog(@"%@",x);

        }];

    }];

//    高级用法

//    switchToLatest:用于signal of signals,获取signal of signals 发出的最新的信号,也就是可以直接拿到RACCommand中的信号

    [command.executionSignals.switchToLatest subscribeNext:^(id x) {

        NSLog(@"高级--%@",x);

    }];

//  ******** 4、监听命令是否执行完毕,默认会来一次,可以直接跳过,skip表示跳过第一次信号

    [[command.executingskip:1]subscribeNext:^(idx) {

        if([xboolValue] ==YES)

        {

//            正在执行

            NSLog(@"正在执行");

        }

        else

        {

//            执行完成

            NSLog(@"执行完成");

        }

    }];

//  ********  5、执行命令

    [self.commandexecute:@1];

//    RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定。

    RAC(self.label,text) = _textField.rac_textSignal;

//  RACObserve(self, name):监听某个对象的某个属性,返回的是信号

    [RACObserve(self.label,text)subscribeNext:^(idx) {

        NSLog(@"%@",x);

    }];

相关文章

网友评论

      本文标题:读书笔记

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