ReactiveObjC Observe 观察 基本类型变量
因为ReactiveObjC
只能监听NSObject
类型的数据,所以一般为了能监听BOOL
值的类型,我们会用NSNumber
来实现BOOL
。
这里介绍一种在不改变BOOL
的情况下,通过封装实现ReactiveObjC
监听BOOL
值类型。
以BOOL
为例:(NSInterger
同理)
一个Person
对象,会在某一时刻更改它的hidden
属性:
@interface MOPerson : NSObject
@property (nonatomic, assign) BOOL hidden;
- (void)updateHidden;
@end
@implementation MOPerson
- (void)updateHidden {
self.hidden = !self.hidden;
}
@end
在VC里持有这个person,点击vc.view时会更改person的hidden值:
代码语言:javascript复制@interface ViewController ()
@property (nonatomic, strong) MOPerson *person;
@end
- (void)viewDidLoad {
[super viewDidLoad];
self.person = [[MOPerson alloc] init];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickSelf)];
[self.view addGestureRecognizer:tap];
}
- (void)clickSelf {
[self.person updateHidden];
NSLog(@"clickSelf: %i", self.person.hidden);
}
下面我们在VC里监听person
的hidden
值:
@interface ViewController () <UITableViewDelegate>
...
@property (nonatomic, assign) BOOL hidden; // 声明一个属性 for 存储观察到的BOOL值
@end
- (void)viewDidLoad {
[super viewDidLoad];
...
RAC(self, hidden, @YES) = RACObserve(self, person.hidden);
...
}
- (void)setHidden:(BOOL)hidden {
_hidden = hidden;
NSLog(@"person hidden did changed: %i", hidden);
}
点击,测试logs:
代码语言:javascript复制person hidden did changed: 0
clickSelf
person hidden did changed: 1
clickSelf
person hidden did changed: 0
另外
如果RACObserve
会重复调用的话,会命中RAC
的Assert
:
is already bound to key path "hidden" on object , adding signal <RACDynamicSignal: 0x600002127620> name: is undefined behavior
需要在下次调用之前unsubscibe
一下:
在UIView
的分类里实现:
// UIView RAC.h
@class RACSignal;
@interface UIView (RAC)
- (RACSignal *)rac_unsubscribeAllSignal;
@end
代码语言:javascript复制// UIView RAC.m
#import <objc/runtime.h>
#import <ReactiveObjC/NSObject RACDescription.h>
#import <ReactiveObjC/NSObject RACSelectorSignal.h>
#import <ReactiveObjC/RACSignal.h>
#import <ReactiveObjC/RACStream.h>
#import <ReactiveObjC/RACUnit.h>
@implementation UIView (RAC)
- (RACSignal *)rac_unsubscribeAllSignal {
RACSignal *signal = objc_getAssociatedObject(self, _cmd);
if (signal != nil) return signal;
signal = [[[self
rac_signalForSelector:@selector(unsubscribeAll)]
mapReplace:RACUnit.defaultUnit]
setNameWithFormat:@"%@ -rac_unsubscribeAllSignal", RACDescription(self)];
objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return signal;
}
/// 取消视图中的所有订阅
/// 注意一定要在视图绑定的model对象发生变更的时候才能调用否则不能调用该方法
- (void)unsubscribeAll {
}
@end
使用:
代码语言:javascript复制[self unsubscribeAll];
RAC(self, hidden, @YES) = [RACObserve(self, person.hidden) takeUntil:self.rac_unsubscribeAllSignal];
参考: How to rebind RACSignal to BOOL variable? ReactiveCocoa 监听布尔(BOOL)类型改变