iOS_ReactiveObjC_Observe 观察 基本类型变量

2022-07-20 14:58:11 浏览数 (2)

ReactiveObjC Observe 观察 基本类型变量

因为ReactiveObjC只能监听NSObject类型的数据,所以一般为了能监听BOOL值的类型,我们会用NSNumber来实现BOOL

这里介绍一种在不改变BOOL的情况下,通过封装实现ReactiveObjC监听BOOL值类型。

BOOL为例:(NSInterger 同理)

一个Person对象,会在某一时刻更改它的hidden属性:

代码语言:javascript复制
@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里监听personhidden值:

代码语言:javascript复制
@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会重复调用的话,会命中RACAssert

代码语言:javascript复制
is already bound to key path "hidden" on object , adding signal <RACDynamicSignal: 0x600002127620> name: is undefined behavior

需要在下次调用之前unsubscibe一下:

UIView的分类里实现:

代码语言:javascript复制
//  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)类型改变

0 人点赞