美文网首页
ReactiveCocoa入门(2)元祖、json解析、应用

ReactiveCocoa入门(2)元祖、json解析、应用

作者: 子疯zp | 来源:发表于2017-05-14 17:41 被阅读80次
    3.3 元祖 RACTuple

    什么叫做元祖?在 swift 中也有所谓的元祖,但是他跟 Objective-C 的数组有点不同。RAC的集合类

    哪里不同呢?

    • swift 中的元祖,他可以放进任何的数据类型!也就是说基本数据类型也能放进去。
    • 但是 Objective-C 中的数组,它就只能放我们的 Objective-C 对象
    • 而 RAC 的元祖,跟我们的 Objective-C 数组其实是一样的,换句话说,它其实就是封装了我们的 Objective-C 数组。

    元祖
    Swift 中的元祖,他可以装进任何类型的数据
    OC 中的数组只能存放对象
    RAC 中的元祖,封装了一层 OC 的数组

    我们来个简单的元祖:

    RACTuple * tuple1 = [RACTuple tupleWithObjectsFromArray:@[@"apple",@"google",@123]]; 
    NSString * str = tuple1[0];
    NSLog(@"%@",str);```
    
    
    它的用法跟我们的数组是一模一样的。
    取出它的第一个元素:`tuple1[0]`
    说白了其实他就是一个数组~
    
    元祖其实只是 RAC 中的一个集合类,他还有其他的集合类。我们来看看其他的集合类是什么样的?
    
    
    ![处理数组 - 遍历.png](https://img.haomeiwen.com/i1859446/6792e7843aa049b3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    **数组遍历**
    只要一行,全部搞定!是不是相对于for循环来说简单多了,主要是编程思想:链式编程、函数编程、响应式编程!
    
    我们来分析一下这段代码,
    前面`array.rac_sequence.signal` 这种连续的点,是练式编程,后面的x 在风里雨里一直等着你,是响应式编程,最后我们再把所有的操作放在block 里面一顿操作,是函数式编程!
    
    一句代码三个愿望一次满足!
    
    **处理字典**
    
    ![处理字典.png](https://img.haomeiwen.com/i1859446/b9ecf6a4469ba812.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    二话不说先将它转成集合,转成集合之后我们创建一个信号,创建信号之后我们订阅这个信号,然后把信号内容全部拿出来
    
    ![](https://img.haomeiwen.com/i1859446/bc417c232083cd99.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    
    他打印了两组数据,也就是两个元祖,每个园组里面分别是key 还有value .所以说x 他是一个id 任意类型,所以我们应该可以把它改成我们的元祖类型然后我们既然把x 当作元祖类型,是不是就是说我们可以用元组类型的方法来调用它?
    
    那就需要用到RAC中的宏`RACTupleUnpack`,RAC里牛逼之一就有它的宏,可以进去学习下!
    
    
    `Unpack` 就是解包的意思,我们来看看怎么去用这个解包的,首先我们要给他赋值,把我们的元祖丢给这个宏。然后在他的参数里面写上参数类型还有参数名字。
    
    在这边其实就是key 跟value
    `RACTupleUnpack(NSString * key, NSString * value) = x;`
    
    然后接下来我们把这个key 跟value 打印出来。
    ![](https://img.haomeiwen.com/i1859446/0a5df30546bb09d2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    所以这边说明了~宏里面的参数其实就是需要被解析出来的变量名称!
    
    
    **解析 json 数据**
    首先创建个plist数据文件
    ![flags.plist.png](https://img.haomeiwen.com/i1859446/6951bb463631a54d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    

    第一步:建立模型

    import <Foundation/Foundation.h>

    @interface FLAGES : NSObject
    @property(copy, nonatomic) NSString * name;
    @property(copy, nonatomic) NSString * icon;

    +(instancetype)flageWithDict:(NSDictionary *)dict;
    @end

    import "FLAGES.h"

    @implementation FLAGES
    +(instancetype)flageWithDict:(NSDictionary *)dict{

    FLAGES * flages = [[FLAGES alloc]init];
    [flages setValuesForKeysWithDictionary:dict];
    return flages;
    

    }
    @end

    第二步:回到我们的控制器 字典转模型
    //3、应用
    // RACSequence 他可以代替我们的数组,也可以代替字典
    // 常用来解析 json 数据,最常使用的场合是 『字典转模型』

    NSString * filePath = [[NSBundle mainBundle]pathForResource:@"flags.plist" ofType:nil];
    NSArray * array2 = [NSArray arrayWithContentsOfFile:filePath];
    
    //一般思维用法
    

    // NSMutableArray * muArray = [NSMutableArray array];
    // [array.rac_sequence.signal subscribeNext:^(NSDictionary * x) {
    //
    // //進行字典轉模型
    // FLAGES * flages = [FLAGES flageWithDict:x];
    // [muArray addObject:flages];
    // }];

    //升级版超爽用法
    //value 集合里面所有的元素
    
    NSArray * modelArray = [[array2.rac_sequence map:^id _Nullable(NSDictionary * value) {
        
        return [FLAGES flageWithDict:value];
    }]array];
    
    NSLog(@"%@",modelArray);
    

    // 我们自己定义了一个可变数组,然后再给他每次接收信号的时候把它转成对象放到术组里面去。

    // 其实我们上下两边做的是一样的事情,此时此刻我们用了map 唯一的不同点是,他拿到了之后需要我们把这个对象给返回出去。因为它会自动帮我们把对象存到一个集合里面去。这个集合可以自动帮我们转成数组,因为它就是一个模型数组。

    
    
    
     ####常见应用
    - 1、监听文本框
    - 2、代替代理 RACSubject
    - 3、代替 KVO
    - 4、代替监听
    - 5、代替通知
    
    首先创建一个button,textFiled用作下面备用:
    

    //1、监听文本框
    [_textF.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
    NSLog(@"%@",x);
    }];

    //2、代替代理 RACSubject (在第一篇中有说到RACSubject的使用,这个就是继承那个的使用方法)
    [[_redView rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(RACTuple * _Nullable x) {
    NSLog(@"%@",x);
    }];

    //3、代替 KVO
    //导入#import "NSObject+RACKVOWrapper.h"

    [[_btn rac_valuesForKeyPath:@"frame" observer:nil] subscribeNext:^(id _Nullable x) {
    NSLog(@"%@",x);
    }];

    //4、代替监听
    //把我们的点击事件当作信号
    [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
    NSLog(@"%@",x);
    }];

    //5、代替通知
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
    NSLog(@"%@",x);
    }];

    
    
    ####利用RAC做一个按钮倒计时
    
    

    //

    import "CountdownViewController.h"

    import "ReactiveObjC.h"

    @interface CountdownViewController ()
    @property (nonatomic, assign) int time;
    @property (nonatomic, strong) RACDisposable *disposable;
    @end

    @implementation CountdownViewController
    -(IBAction)timeBtnClick:(UIButton *)sender {

    sender.enabled = NO;
    
    _time = 30;
    
    
    //如果没有把 RACDisposable 强引用,RAC会给它自动转弱,执行一次完了
    self.disposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {
        //更新UI 设置按钮上的文字
        //1、time > 0  , 按钮上的时间倒计时
        //2、time <= 0 , 按钮上显示【重新发送】
        
        
        
        //感觉太low了 下面改进
    

    // if (_time > 0) {
    // sender.enabled = NO;
    // [sender setTitle:[NSString stringWithFormat:@"%ds",_time] forState:UIControlStateNormal];
    // }else{
    // sender.enabled = YES;
    // [sender setTitle:@"重新发送" forState:UIControlStateNormal];
    //
    // //关闭 timer (取消订阅)
    // [_disposable dispose];
    // }

        NSString *btnTitle = _time > 0 ? [NSString stringWithFormat:@"%ds",_time] : @"重新发送";
        [sender setTitle:btnTitle forState:UIControlStateNormal];
        
        
        
        if (_time > 0) {
            sender.enabled = NO;
        }else{
            sender.enabled = YES;
            //关闭 timer (手动取消订阅)
            [_disposable dispose];
        }
        
        _time --;
        
    }];
    
    
    //滑动scrollView,timer不受影响
    

    }
    -(void)dealloc{

    //只有当倒计时结束了,才会dealloc
    NSLog(@"我走了");
    

    }

    
    >上述代码可以到我的[GitHub](https://github.com/zpHao/ReactiveCocoa-primary)中下载
    
    有错误,有问题的欢迎提出来!😊
    
    
    
    *未完待续...*

    相关文章

      网友评论

          本文标题:ReactiveCocoa入门(2)元祖、json解析、应用

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