美文网首页从0到1学习RAC
iOS ReactiveCocoa学习笔记(3):信号传递与数据

iOS ReactiveCocoa学习笔记(3):信号传递与数据

作者: 一粒咸瓜子 | 来源:发表于2019-06-13 19:00 被阅读3次

本文知识点:RAC信号传递、RACSequence、RACTuple、利用RAC进行字典转模型。

1.RAC信号传递

  • 代替代理: rac_signalForSelector:用于替代代理。
  • 代替KVO: rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变。
  • 监听事件: rac_signalForControlEvents:用于监听某个事件。
  • 代替通知: rac_addObserverForName:用于监听某个通知。
  • 监听文本框文字改变: rac_textSignal: 只要文本框发出改变就会发出这个信号。
  • 代替调度组:当界面有多次请求时,需要都获取到数据时,才能展示界面: rac_liftSelector:withSignalsFromArray:Signals: 当传入的 Signals (信号数组),每一个 signal 都至少 sendNext 过一次,就会去触发第一个 selector 参数的方法。
    • 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。

1.1 代码演示

A.常用控件RAC都有封装signal方法
Ex1:UIButton

//将UIControlEventTouchUpInside这个事件类型转换为信号
[[self.tapBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id  _Nullable x) {
    NSLog(@"按钮被点击啦");
}];

Ex2:手势

UITapGestureRecognizer *restureRecognizer = [UITapGestureRecognizer new];
[self addGestureRecognizer:restureRecognizer];
[[restureRecognizer rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
    NSLog(@"手势");
}];

B. UIControl Send action & target

//view发出valueChanged事件
[[view rac_signalForControlEvents:UIControlEventValueChanged] subscribeNext:^(__kindof UIControl * _Nullable x) {
    NSLog(@"%@",x);
}];

C. 代理 rac_signalForSelector

//当view内部的method方法被执行时
[[view rac_signalForSelector:@selector(method)] subscribeNext:^(RACTuple * _Nullable x) {
    ...
}];

D. 通知 rac_addObserverForName

UITextField *tf1 = [[UITextField alloc] initWithFrame:CGRectMake(30, 30, 200, 50)];
tf1.borderStyle = UITextBorderStyleLine;
[self.view addSubview:tf1];
    
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillChangeFrameNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
    NSLog(@"%@", x);
}];

E. KVO rac_valuesAndChangesForKeyPath

_mArray = [NSMutableArray array];
[[self rac_valuesAndChangesForKeyPath:@"mArray" options:0 observer:self] subscribeNext:^(RACTwoTuple<id,NSDictionary *> * _Nullable x) {
    NSLog(@"%@", x);
}];   
[[self mutableArrayValueForKeyPath:@"mArray"] addObject:@1];
[[self mutableArrayValueForKeyPath:@"mArray"] addObject:@2];

Output:
2018-04-03 18:13:57.959540+0800 RACDemo[11295:583320] (
    1
)
2018-04-03 18:13:57.959898+0800 RACDemo[11295:583320] (
    1,
    2
)

2.RAC数据对象

2.1 RACTuple

元组类,类似 NSArray,用来包装多个值。
解包元组:RACTupleUnpack(NSString *key, NSString *value) = x
会把元组的值 按顺序给参数里面的变量赋值。宏定义如下:

#define RACTupleUnpack_(...) \
    metamacro_foreach(RACTupleUnpack_decl,, __VA_ARGS__) \
    \
    int RACTupleUnpack_state = 0; \
    \
    RACTupleUnpack_after: \
        ; \
        metamacro_foreach(RACTupleUnpack_assign,, __VA_ARGS__) \
        if (RACTupleUnpack_state != 0) RACTupleUnpack_state = 2; \
        \
        while (RACTupleUnpack_state != 2) \
            if (RACTupleUnpack_state == 1) { \
                goto RACTupleUnpack_after; \
            } else \
                for (; RACTupleUnpack_state != 1; RACTupleUnpack_state = 1) \
                    [RACTupleUnpackingTrampoline trampoline][ @[ metamacro_foreach(RACTupleUnpack_value,, __VA_ARGS__) ] ]

代码演示:

NSDictionary *dict = @{@"name":@"aab",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
    // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
    RACTupleUnpack(NSString *key, NSString *value) = x;
    NSLog(@"%@, %@", key, value);
}];

Output:
2018-04-04 14:25:35.309629+0800 RACDemo[28438:896531] name, aab
2018-04-04 14:25:35.310345+0800 RACDemo[28438:896531] age, 18

2.2 RACSequence

RAC 中的集合类,用来替代 NSArray、NSDictionary,可以使用它来快速遍历数组和字典。

  • 第一步: 把数组转换成集合 RACSequence。
  • 第二步: 把集合 RACSequence 转换 RACSignal 信号类。
  • 第三步: 订阅信号,激活信号,会自动把集合中的所有值,遍历出来。

Array:

NSArray *array = @[@1, @2, @3];
[array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
    NSLog(@"%@", x);
}];

Output:
2018-04-04 14:21:08.937986+0800 RACDemo[28313:891089] 1
2018-04-04 14:21:08.938413+0800 RACDemo[28313:891089] 2
2018-04-04 14:21:08.938843+0800 RACDemo[28313:891089] 3

Dictionary:

NSDictionary *dict = @{@"name":@"aab",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
    // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
    RACTupleUnpack(NSString *key, NSString *value) = x;
    NSLog(@"%@, %@", key, value);
}];

Output:
2018-04-04 14:25:35.309629+0800 RACDemo[28438:896531] name, aab
2018-04-04 14:25:35.310345+0800 RACDemo[28438:896531] age, 18

2.3 使用场景:字典转模型

2.3.1 基础版

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"students" withExtension:@"plist"];
NSArray *array = [NSArray arrayWithContentsOfURL:fileURL];

NSMutableArray <Person *> *mArray = [NSMutableArray array];
@weakify(self);
[array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
    Person *person = [Person modelWithDict: x];
    [mArray addObject:person];
} completed:^{
    @strongify(self);
    self.dataArray = mArray.copy;
}];
//_dataArray = mArray.copy 写在外面无效。调用subscribeNext,并不会马上执行nextBlock,而是会等一会。

2.3.2 进阶版

方式:map 函数(遍历集合所有子元素并映射成一个新值)
toArray: 把集合转换成数组
底层实现:当信号被订阅,会遍历集合中的原始值,映射成新值,并且保存到新的数组里。

_dataArray = [[array.rac_sequence.signal map:^id _Nullable(id  _Nullable value) {
    return [Person modelWithDict:value];
}] toArray];

相关文章

网友评论

    本文标题:iOS ReactiveCocoa学习笔记(3):信号传递与数据

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