ReactiveObjC简介
最正确的方式要从读官方文档ReactiveObjc 开始
ReactiveObjC 是一个函数式响应式编程框架(functional reactive programming),不是Rx系列的。
Rx系列只是一种函数响应式的扩展,相比就很轻量。目前iOS的Rx系列只有RxSwift,需要单独学习😊
为啥要用它?
它提供了统一的方法来处理异步行为[1]。
常用的几种方式:delegate、target-action、NSNotificationCenter、KVO、blcok
1、delegate
比如要实时监听输入框的文字,限制字数、校验邮箱等等操作
传统写法
@interface ViewController ()< UITextFieldDelegate >
...
self.textField.delegate = self;
...
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
// 处理逻辑
}
RAC写法
[[self.textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"textfield.text -- %@",x);
}];
2、target-action
常用与Button
的点击事件
传统写法
[self.btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
...
- (void)btnClick:(UIButton *)btn{
// 处理点击事件
}
RAC写法
[[self.btn rac_signalForControlEvents:(UIControlEventTouchUpInside)] subscribeNext:^(__kindof UIControl * _Nullable x) {
// 处理点击事件
}];
3、NSNotificationCenter & KVO
传统写法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
...
- (void)didEnterBackground{
// 处理事件
}
// KVO
static void *ObservationContext = &ObservationContext;
[LoginManager.sharedManager addObserver:self forKeyPath:@"loggingIn" options:NSKeyValueObservingOptionInitial context:&ObservationContext];
...
- (void)dealloc {
[LoginManager.sharedManager removeObserver:self forKeyPath:@"loggingIn" context:ObservationContext];
[NSNotificationCenter.defaultCenter removeObserver:self];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == ObservationContext) {
// 处理事件
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
RAC写法
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
// 处理事件
}];
// KVO
[RACObserve(LoginManager.sharedManager, loggingIn) subscribeNext:^(id _Nullable x) {
// 处理事件
}];
4、Block
例如AFNetworking
网络请求成功、失败,往往都以block
作为参数实现。
传统写法
AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];
[sessionManager GET:@"url" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
-
RAC写法
先创建继承AFHTTPSessionManager
,用单例操作
- (RACSignal *)signalGet:(NSString *)url param:(id)param{
// 返回信号量
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 内部调用GET方法
[self GET:url parameters:param progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[subscriber sendNext:responseObject];
[subscriber sendCompleted];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[subscriber sendError:error];
}];
return nil;
}];
}
...
[[[RACHttpManager shareRACHttpManager] signalGet:@"url" param:nil] subscribeNext:^(id _Nullable x) {
// 成功的信号
} error:^(NSError * _Nullable error) {
// 失败的信号
}];
感觉差别不大😁,那是因为还没有深入的讲到信号量的作用,以及文档中反复提到的futures and promises
[2]概念,掘金翻译的这篇文章很好的解释了。
怎么集成
可以在Cocoapods搜索ReactiveObjC
看下
pod 'ReactiveObjC'
-
ReactiveObjc 简介中出现这句 "One of the major advantages of RAC is that it provides a single, unified approach to dealing with asynchronous behaviors, including delegate methods, callback blocks, target-action mechanisms, notifications, and KVO." ↩
-
ReactiveObjc 讲异步操作嵌套的解决办法中提到 "Signals can be chained to sequentially execute asynchronous operations, instead of nesting callbacks with blocks. This is similar to how futures and promises are usually used:
"cf ↩