我们要看懂RAC中的KVO功能,不得不看懂里面用的一些宏、关键字
// 1. @onExit 在离开作用域的时候执行@onExit{}大括号里的代码; 注意,同一个作用域下,后定义的@onExit先执行。
[objectLock lock];
@onExit {
[objectLock unlock];
};
// 2. __attribute__ 设置类型属性
// 3.objc_precise_lifetime 告诉ARC,在引用变量超出范围之前,不允许释放对象
__strong NSObject *observer __attribute__((objc_precise_lifetime)) = weakObserver;
// 4. 常用的@weakify(self)将self转为弱引用self_weak_、@strongify(self)定义self指针赋值为self_weak_
// 5. RACObserve创建KVO监听信号
RACObserve(self.Obj, nickName)
// 6. RAC(self.loginViewModel,phoneNumber) 给值绑定一个信号
//绑定手机号 这样写可以self.loginView.PhoneTF.text = 复制时也能调用
RAC(self.loginViewModel,phoneNumber ) = [RACSignal merge:@[RACObserve(self.loginView.phoneTF, text),self.loginView.phoneTF.rac_textSignal]];
// 7. @keypath能识别到类头文件中的属性
[target_ rac_valuesForKeyPath:@keypath(self.person, iconName) observer:self];
一些生疏的数据结构:
一、元组RACTuple
RACTuple是一个存储有序元素的容器类,对OC数组的一层封装, 跟数组类似。
RACTuple *tuple = [RACTuple tupleWithObjects:@"111", @"222", nil];
id first = tuple[0];
// tuple[0];这个语法可以像数组一样用“[]”来取得下标元素.
// 原因是实现了下面方法的类都可以。
- (id)objectAtIndexedSubscript:(NSUInteger)idx {
return [self objectAtIndex:idx];
}
二、序列RACSequence
有了这个数据结构,我们可以很方便的为集合类型数据创建信号,遍历起来只需要订阅信号subscribeNext:
, 而且是在子线程完成遍历的。
// 1、数组
NSArray * array = @[@"牛年大牛",@"落地成盒",@66666,@99999];
[array.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 2、字典
NSDictionary * dict = @{@"大吉大利":@"今晚吃鸡",
@"666666":@"999999",
@"dddddd":@"aaaaaa"
};
[dict.rac_sequence.signal subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"dict.rac_sequence.signal:currentThread== %@", [NSThread currentThread]);
NSLog(@"key - %@ value - %@",x[0],x[1]);
}];
三、信号bind
信号调用bind:
方法后执行绑定,内部会生成一个新的信号,订阅绑定后的信号时后,在原来信号发送时,我们订阅中得到的值是做过处理的值。如下:
- (void)testBind{
RACSubject *subject = [RACSubject subject];
RACSignal * signal = [subject bind:^RACSignalBindBlock _Nonnull{
return ^RACSignal *(id _Nullable value, BOOL *stop){
NSDictionary *map = @{@"key1": @"key2",
@"111": @"222"};
return [RACReturnSignal return:map[value]];
};
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"收到的数据 - %@",x); // 收到的是222
}];
[subject sendNext:@"111"];
}
四、信号map、flattenMap
RAC中提供了信号的映射功能,我们对信号调用map或flattenMap
方法后,再对信号进行订阅,我们收到的信号值是经过映射后的值. 内部的实现原理是用的bind
。
// FlattenMap更针对信号的映射,将信号映射成新的信号
- (void)testFlattenMap{
RACSubject * subject = [RACSubject subject];
RACSignal * signal = [subject flattenMap:^__kindof RACSignal * _Nullable(NSString *value) {
return [RACReturnSignal return:[@"flattenMap " stringByAppendingString:value]];
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"111"];
[subject sendNext:@"222"];
[subject sendNext:@"333"];
}
// map更针对值的映射,映射成新的值
- (void)testMap{
RACSubject * subject = [RACSubject subject];
[[subject map:^id _Nullable(id _Nullable value) {
return [NSString stringWithFormat:@"%@ 你别问我,我也不知道!",value];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"what happend?"];
}
网友评论