ReactiveCocoa / RxSwift 笔记一
原创:转载请注明出处
ReactiveCocoa / RxSwift
Native app有很大一部分的时间是在等待事件发生,然后响应事件,比如
1.等待网络请求完成,
2.等待用户的操作,
3.等待某些状态值的改变等等,
等这些事件发生后,再做进一步处理
但是这些等待和响应,并没有一个统一的处理方式。Delegate, Notification, Block, KVO, 常常会不知道该用哪个最合适。有时需要chain或者compose某几个事件,就需要多个状态变量,而状态变量一多,复杂度也就上来了。为了解决这些问题,Github的工程师们开发了ReactiveCocoa。
概念
插座:Signal -> 插座负责去获取并提供电 <—> Observable
插头:Subscriber -> 插头负责使用电 <—> Observer
用途
Signal 获取到数据后,会调用Subscriber的sendNext, sendComplete, sendError方法来传送数据给Subscriber,
<>
RxSwift : onNext onComplete onError
Subscriber 自然也有方法来获取传过来的数据,如:[signal subscribeNext:error:completed]。这样只要没有sendComplete和sendError,新的值就会通过sendNext源源不断地传送过来
<>
RxSwift:
reloadDataItem.rx_tap
.subscribeNext { [unowned self] in
self.initialization()
}.addDisposableTo(disposeBag)
RAC 是基于KVO的
原理:
RACObserve使用了KVO来监听property的变化,只要username被自己或外部改变,block就会被执行。但不是所有的property都可以被RACObserve,该property必须支持KVO,比如NSURLCache的currentDiskUsage就不能被RACObserve.
灵活性:
Signal是很灵活的,它可以被修改(map),过滤(filter),叠加(combine),串联(chain),这有助于应对更加复杂的情况,
RAC(self.logInButton, enabled) = [RACSignal
combineLatest:@[
self.usernameTextField.rac_textSignal,
self.passwordTextField.rac_textSignal,
RACObserve(LoginManager.sharedManager, loggingIn),
RACObserve(self, loggedIn)
] reduce:^(NSString *username, NSString *password, NSNumber *loggingIn, NSNumber *loggedIn) {
return @(username.length > 0 && password.length > 0 && !loggingIn.boolValue && !loggedIn.boolValue); }];
1.只要usernameTextField的值有变化,这个值就会被返回(sendNext)。
2.combineLatest需要每个signal至少都有过一次sendNext。
3.reduce的作用是根据接收到的值,再返回一个新的值,这里是@(YES)和@(NO),必须是object。
<>
RxSwift:
Observable.combineLatest(calendarRequest, scheduleRequest, calendarVC.rx_didScrollToMonth) {
(scheduleList: $0, schedule: $1, didScroll:$2)
}
.onAlertError()
.subscribe(
onNext: { [unowned self] x in
//self.updateData(x.scheduleList, schedule: x.schedule, noticeList: nil)
},
onError: { [unowned self] error in
//
},
onCompleted: {
//
}
).addDisposableTo(self.disposeBag)
Side Effect
还是上面那段代码,如果有多个subscriber,那么signal就会又一次被触发,控制台里会输出两次triggered。这或许是你想要的,或许不是。如果要避免这种情况的发生,可以使用 replay 方法,它的作用是保证signal只被触发一次,然后把sendNext的value存起来,下次再有新的subscriber时,直接发送缓存的数据。
Cocoa Categories
UIView Categories
1. [[alertView rac_buttonClickedSignal] subscribeNext:^(NSNumber *indexNumber) {
//toDo
}];
RAC给UITableViewCell提供了一个方法:rac_prepareForReuseSignal,它的作用是当Cell即将要被重用时,告诉Cell。想象Cell上有多个button,Cell在初始化时给每个button都addTarget:action:forControlEvents,被重用时需要先移除这些target,下面这段代码就可以很方便地解决这个问题:
- [[[self.cancelButton
- rac_signalForControlEvents:UIControlEventTouchUpInside]
- takeUntil:self.rac_prepareForReuseSignal]
- subscribeNext:^(UIButton *x) {
- // do other things
- }];
rac_command,就是当button被按下时会执行的一个命令,命令被执行完后可以返回一个signal,有了signal就有了灵活性。比如点击投票按钮,先判断一下有没有登录,如果有就发HTTP请求,没有就弹出登陆框,可以这么实现。
NotificationCenter Category
NSNotificationCenter, 默认情况下NSNotificationCenter使用Target-Action方式来处理Notification,这样就需要另外定义一个方法,这就涉及到编程领域的两大难题之一:起名字。有了RAC,就有Signal,有了Signal就可以subscribe,于是NotificationCenter就可以这么来处理,还不用担心移除observer的问题。
- [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"MyNotification" object:nil] subscribeNext:^(NSNotification *notification) {
- NSLog(@"Notification Received");
- }];
NSObject+RACDeallocating.h
顾名思义就是在一个object的dealloc被触发时,执行的一段代码。
- NSArray *array = @[@"foo"];
- [[array rac_willDeallocSignal] subscribeCompleted:^{
- NSLog(@"oops, i will be gone");
- }];
- array = nil;
NSObject+RACSelectorSignal.h
这个category有rac_signalForSelector:和rac_signalForSelector:fromProtocol: 这两个方法。先来看前一个,它的意思是当某个selector被调用时,再执行一段指定的代码,相当于hook。比如点击某个按钮后,记个日志。后者表示该selector实现了某个协议,所以可以用它来实现Delegate。
MVVM
MVVM跟MVC最大的区别是多了个ViewModel,它直接与View绑定,而且对View一无所知。拿做菜打比方的话,ViewModel就是调料,它不关心做的到底是什么菜。它可以扮演Model的职责,但其实它是Model的中介,这样当Model的API有变化,或者由本地存储变为远程API调用时,ViewModel的public API可以保持不变。
使用ViewModel的好处是,可以让Controller更加简单和轻便,而且ViewModel相对独立,也更加方便测试和重用。那Controller这时又该做哪些事呢?在MVVM体系中,Controller可以被看成View,所以它的主要工作是
处理布局、
动画、
接收系统事件、
展示UI。
MVVM还有一个很重要的概念是 data binding,view的呈现需要data,这个data就是由ViewModel提供的,将view的data与ViewModel的data绑定后,将来双方的数据只要一方有变化,另一方就能收到。这里有Github 开源的一个ViewModel Base Class。
其他
RAC在使用时有一些注意事项,可以参考官方的DesignGuildLines,这里简单说一下。
当一个signal被一个subscriber subscribe后,这个subscriber何时会被移除?答案是当subscriber被sendComplete或sendError时,或者手动调用[disposable dispose]。
当subscriber被dispose后,所有该subscriber相关的工作都会被停止或取消,如http请求,资源也会被释放。
Signal events是线性的,不会出现并发的情况,除非显示地指定Scheduler。所以-subscribeNext:error:completed:里的block不需要锁定或者synchronized等操作,其他的events会依次排队,直到block处理完成。
Errors有优先权,如果有多个signals被同时监听,只要其中一个signal sendError,那么error就会立刻被传送给subscriber,并导致signals终止执行。相当于Exception。
生成Signal时,最好指定Name, -setNameWithFormat: 方便调试。
block代码中不要阻塞。
ReactiveCocoa / RxSwift 笔记一的更多相关文章
- iOS开发ReactiveCocoa学习笔记(六)
RAC操作方法三. demo地址:https://github.com/SummerHH/ReactiveCocoa.git doNext deliverOn timeout interval del ...
- iOS开发ReactiveCocoa学习笔记(五)
ReactiveCocoa常见操作方法介绍: demo地址:https://github.com/SummerHH/ReactiveCocoa.git filter ignore ignoreValu ...
- iOS开发ReactiveCocoa学习笔记(四)
ReactiveCocoa常见操作方法介绍: demo地址:https://github.com/SummerHH/ReactiveCocoa.git 1.1 ReactiveCocoa操作须知 所有 ...
- iOS开发ReactiveCocoa学习笔记(二)
RAC 中常见的宏: 使用宏定义要单独导入 #import <RACEXTScope.h> 一. RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某 ...
- iOS开发ReactiveCocoa学习笔记(一)
学习 RAC 我们首先要了解 RAC 都有哪些类 RACSignal RACSubject RACSequence RACMulticastConnection RACCommand 在学习的时候写了 ...
- ReactiveCocoa学习笔记--用法
1.监测UI变量的变化 return 后把值传递下去. 1.1.输出 [self.usernameTextField.rac_textSignal subscribeNext:^(id x){ NSL ...
- iOS开发ReactiveCocoa学习笔记(三)
RAC常用用法: 1.监听按钮的点击事件: UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame ...
- ReactiveCocoa学习资料
ReactiveCocoa 学习资料: ReactiveCocoa入门教程:第一部分 http://www.cocoachina.com/ios/20150123/10994.html Reactiv ...
- ReactiveCocoa 学习资料
之前就有听说,感觉很强大,ReactiveCocoa更加被Mattt Thompson大神称为开启一个新Objective-C纪元.所以觉得非常有学习的必要了. 一些很好的学习资料: Reactive ...
随机推荐
- Myeclipse 激活代码 8.6以前的版本
public class Akey { private static final String LL = "Decompiling this copyrighted software is ...
- gcc-config: Active gcc profile is invalid解决办法
错误描述 Gentoo软件安装错误,提示: gcc-config: Active gcc profile is invalid 解决方法: 列出可用的profile gcc-config -l gcc ...
- 高精度运算专题-输出函数与字符串转数字函数(Output function and the string to number function)
输出函数:这个函数别看它小,但浓缩的都是精华啊 作用:对于高精度的数组进行倒序输出 思路:首先从被传入的数组第一位开始,一直往前扫输出就可以了(i--) 注释:因为每个数组的第一位是用来存储这个数组的 ...
- MySQL Administrator的简单操作
A.创建数据库 1.运行MySQL Administrator服务器,如下图. 2.点击"Catalogs",下面出现已有的数据库,右击已有的数据库,选择“Create New S ...
- Gitlab 安装配置
Gitlab 很好的替代Github,可以安装到公司的内网服务器 进行管理 ,可以分布式的管理,集中的管理 下面介绍安装这个软件的步骤 其实安装很简单的 按照官网可以安装 https://about ...
- RPC简介与Thrift框架
RPC,全称是remote process call,远程过程调用,简单来讲就是调用部署在另一台服务器上的服务或者被部署在另一台服务器上的服务调用.由于各服务部署在不同机器,服务间的调用免不了网络通信 ...
- Google 怎么搜索
著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:崔凯 链接:http://www.zhihu.com/question/20161362/answer/14180620 ...
- applicationhost.config web.config
在 IIS7 8两个版本中, 用户的配置,可以通过修改如上的配置文件来完成 applicationhost.config ,可以定义全局的 用户自己目录下的web.config,可以自己定义 但是,有 ...
- WEB 端批量移动设备管理控制工具 STF 的环境搭建和运行
最近项目涉及到较多设备批量管理的需求,发现一工具,可以批量对大量设备进行WEB端管理,工具主页:https://openstf.github.io/工具名STF(Smartphone Test Far ...
- CSS3秘笈:第二章
1.一个样式由两个元素组成:浏览器对其设置格式的网页元素(选择器,selector)和实际的格式化指令(声明块,declaration block). 2.简单的样式也包含了以下几个元素: (1)Se ...