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

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

数组遍历
只要一行,全部搞定!是不是相对于for循环来说简单多了,主要是编程思想:链式编程、函数编程、响应式编程!

我们来分析一下这段代码,
前面array.rac_sequence.signal 这种连续的点,是练式编程,后面的x 在风里雨里一直等着你,是响应式编程,最后我们再把所有的操作放在block 里面一顿操作,是函数式编程!

一句代码三个愿望一次满足!

处理字典

处理字典.png

二话不说先将它转成集合,转成集合之后我们创建一个信号,创建信号之后我们订阅这个信号,然后把信号内容全部拿出来

他打印了两组数据,也就是两个元祖,每个园组里面分别是key 还有value .所以说x 他是一个id 任意类型,所以我们应该可以把它改成我们的元祖类型然后我们既然把x 当作元祖类型,是不是就是说我们可以用元组类型的方法来调用它?

那就需要用到RAC中的宏RACTupleUnpack,RAC里牛逼之一就有它的宏,可以进去学习下!

Unpack 就是解包的意思,我们来看看怎么去用这个解包的,首先我们要给他赋值,把我们的元祖丢给这个宏。然后在他的参数里面写上参数类型还有参数名字。

在这边其实就是key 跟value
RACTupleUnpack(NSString * key, NSString * value) = x;

然后接下来我们把这个key 跟value 打印出来。

所以这边说明了~宏里面的参数其实就是需要被解析出来的变量名称!

解析 json 数据
首先创建个plist数据文件
flags.plist.png

第一步:建立模型
#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中下载

有错误,有问题的欢迎提出来!��

未完待续…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值