首先简单介绍一下RAC是个什么东西。RAC全称ReactiveCocoa,是GitHub开源的一个函数响应式编程(FRP)库。
Signal 与 Subscriber
可以说这是RAC核心最核心的两个概念。Signal好比是光纤中传输的数字信号,而Subscriber是我们每个人家里的光猫。我们打开了家里的光猫才能正常上网,Signal 与 Subscriber就是这个互相配合工作的。
首先我们看看RACSubscriber的API
@protocol RACSubscriber <NSObject>
@required
- (void)sendNext:(nullable id)value;
- (void)sendError:(nullable NSError *)error;
- (void)sendCompleted;
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;
@end
Subscriber通过sendNext、sendError、sendCompleted等方法获取由Signal传输过来的数据。用法如下:
RACSignal *signal = RACObserve(self, clueArray);
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
上述例子我们监听了一个全局变量数组,在它发生变化时我们可以做自己想做的操作,比如更新UI、给服务器上传数据变化等等。
这里就暂时初步做个介绍吧, 深入的理解等我搞清楚了在写吧,本篇只介绍简单的用法。
RAC实用的API:
- 1 代替target-action
[[self.confirmButton rac_signalForControlEvents:UIControlEventTouchUpInside]
subscribeNext:^(id x) {
// 回调内容写在这里
}];
- 2 代替delegate
[[self.scrollView rac_signalForSelector:@selector(scrollViewDidScroll:) fromProtocol:@protocol(UIScrollViewDelegate)]
subscribeNext:^(id x) {
// 回调内容写在这里
}];
- 3 代替block
[[self asyncProcess] subscribeNext:^(id x) {
// 回调内容写在这里
} error:^(NSError *error) {
// 错误处理写到这里
}];
- 4 代替notification center
//订阅通知
@weakify(self)
[[[kNotificationCenter rac_addObserverForName:kOperateReturnNotificationNameUpdate object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * _Nullable x) {
@strongify(self)
[self fetchData];
}];
- 5 代替KVO
[RACObserve(self, name) subscribeNext:^(id x) {
// 回调内容写在这里
}];
- 6 单向绑定
//当两个TextField的text长度都大于零,确认按钮才能点击
RAC(self.confirmItem, enabled) = [RACSignal combineLatest:@[self.userNameTextField.rac_textSignal,
self.passwordTextField.rac_textSignal,]
reduce:^id _Nullable{
return @(self.userNameTextField.text.length > 0 && self.passwordTextField.text.length > 0);
}];
- 7 双向绑定
//Model与View互相影响。当textField的text改变,model对应的值也跟着改变。反之,也成立。
RACChannelTo(self.someLabel, text) = RACChannelTo(self.viewModel, someProperty);
[self.textField.rac_newTextChannel subscribe:self.viewModel.someChannel];
[self.viewModel.someChannel subscribe:self.textField.rac_newTextChannel];
RACChannelTo(self, reviewID) = self.viewModel.someChannel;
这里就列举以上几种,初步了解一下。
RAC中常见的几个宏
- 1 RACObserve(TARGET, KEYPATH);
//用于监听person对象的name属性
RACObserve(self.person, name)
- 2 RAC(TARGET, ...);
//将self.nameLabel.text 与 self.person.name绑定
RAC(self.nameLabel, text) = RACObserve(self.person, name);
- 3 weakify(...)
//防止循环引用
@weakify(self)
[[[kNotificationCenter rac_addObserverForName:kOperateReturnNotificationNameUpdate object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * _Nullable x) {
@strongify(self)
[self fetchData];
}];
虽然一般公司的项目都不那么复杂,用不上RAC,但是RAC作为一个工具库,也能提供一些比较便捷的解决问题的方案,所以了解一些RAC的知识还是有必要的。
另外,MVVM解决了Controller臃肿的弊病,但也出现了一些新的问题。而MVVM+RAC完美的解决了这些问题,这也体现出RAC的强大。
最后,附上一个MVVM场景下RAC的使用实例:
- 1 ViewModel中的数据请求封装:
+ (RACSignal *)fetchData {
RACReplaySubject *subject = [RACReplaySubject subject];
NSURLRequest *request = [self popularURLRequest];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError){
if (data) {
id results = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
[subject sendNext:[[[results[@"photos"] rac_sequence] map:^id(NSDictionary *photoDictionary) {
FRPPhotoModel * model = [FRPPhotoModel new];
[self configurePhotoModel:model withDictionary:photoDictionary];
[self downloadThumbnailForPhotoModel:model];
return model;
}] array]];
[subject sendCompleted];
} else {
[subject sendError:connectionError];
}
}];
return subject;
}
- 2 监听数据源数组,刷新UI
@weakify(self);
[RACObserver(self, dataArray) subscribeNext:^(id x){
@strongify(self);
[self.tableView reloadData];
}];
- 3 VC中调用请求数据方法
- (void)loadPopularPhotos{
[[DataViewModel fetchData] subscribeNext:^(id x){
self.dataArray = x;
} error:^(NSError * error){
NSLog(@"%@",error);
}];
}
网友评论