iOS ReactiveCocoa(RAC)学习详解
概述:
ReactiveCocoa(简称为RAC
),是由Github开源的一个应用于iOS和OS开发的一个框架,有时间,自己也了解学习了一下这个框架的一些基本的应用,其实你要学的话网上是有很多很多的博客给你去仔细的学习这个框架,我也把自己看到的觉得很不错的博客整理出来,方便大家以后学习也方便自己巩固这些知识!
ReactiveCocoa是做什么的?
引述自己学习的《最快让你上手ReactiveCocoa之基础篇》这篇博客里面的概述,说说 ReactiveCocoa 的作用;
- 在我们iOS开发过程中,当某些事件响应的时候,需要处理某些业务逻辑,这些事件都用不同的方式来处理。
- 比如按钮的点击使用action,ScrollView滚动使用delegate,属性值改变使用KVO等系统提供的方式。
- 其实这些事件,都可以通过RAC处理
- ReactiveCocoa为事件提供了很多处理方法,而且利用RAC处理事件很方便,可以把要处理的事情,和监听的事情的代码放在一起,这样非常方便我们管理,就不需要跳到对应的方法里。非常符合我们开发中
高聚合,低耦合
的思想。
这是博客里面作者的概述,其实作者已经说的很明白了,简单点的一句话总结,ReactiveCocoa 其实就是一个用来帮我们处理事件的一个三方的框架!
学习的博客里面是通过总结我们常见编程思想来入手给我们讲解ReactiveCocoa这个框架的,把所知的编程思想罗列出来,你要觉得你还是没有理解这些编程思想或者有所疑惑的话,你都可以去上网搜搜或者翻翻我学习的文章去看看。
一 面相对象:处理事情以过程为核心,一步一步的实现。
解释:用以前常说的怎么把大象放在冰箱里面为例,你要从面向过程去考虑的话你就得一步一步的把这个整个过程拆分开去做。
第一步:把大象剁了(当然,只是这样说说而已,别真的这样做,我们还是要保护大象!只为解释一下这个面相过程的思想O(∩_∩)0)。
第二步:把冰箱门打开。
第三步:一块块的把大象放进去。
第四步:把冰箱门关上,这就是面相过程你所需要考虑的。
二 面相对象:万物皆对象
同样以上面的过程为例,你需要考虑的只是把冰箱打开,把大象放进去就行了,至于怎么放这些步骤你就不需要考虑了,我们只关心对象,不关心过程。
三 链式编程思想:关注于数据流和变化传播,是将多个操作通过点号(.)链接在一起成为一句代码,使代码可读性好。像这样调用a(1).b(2).c(3)
代表:masonry框架。
四 响应式编程思想:不需要考虑调用顺序,只需要知道考虑结果,类似于蝴蝶效应,产生一个事件,会影响很多东西,这些事件像流一样的传播出去,然后影响结果,借用面向对象的一句话,万物皆是流。
代表:KVO运用。
五 函数式编程思想
:例如函数用其他函数作为参数。
代表:ReactiveCocoa。
上面这么多,就把它的作用和它所用的编程思想做了一个类比和分析。看看它的基本的使用:
先说说安装:
这个的话我自己是强烈建议使用Cocoapods的,还不知道怎么安装的看以前的博客《CocoaPods 2016最新安装和使用说明》,把安装的终端代码给大家参考:
target 'RaectiveCocoaTest' do use_frameworks! pod 'ReactiveCocoa', '~>4.0.2-alpha-1' end
ReactiveCocoa 的使用:
三方开头头文件先行:#import "ReactiveCocoa"
一 RACSiganl (信号类):你可以把下面代码放在你的控制器当中运行一遍,我们看着代码解释这个类;
RACSignal * singel = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { // subscriber 是订阅者,这是一个协议,不是一个类。发送信号 1 [subscriber sendNext:@2]; // 发送完成 [subscriber sendCompleted]; // RACDisposable:用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。 // 执行完Block后,当前信号就不在被订阅了。 return [RACDisposable disposableWithBlock:^{ NSLog(@"信号被销毁"); }]; }]; //singel信号类调用subscribeNext方法订阅信号。订阅之后才会激活这个信号,注意顺序! [singel subscribeNext:^(id x) { // block调用时刻:每当有信号发出数据,就会调用block. NSLog(@"接收到数据:%@",x); }];
XCode打印出:
2016-08-09 15:12:53.437 RaectiveCocoaTest[21421:170391] 接收到数据:2
2016-08-09 15:12:53.438 RaectiveCocoaTest[21421:170391] 信号被销毁
解释:
1:RACSiganl(信号类)只是表示当数据改变时,信号内部会发出数据,它本身不具备发送信号的能力,而是交给内部一个订阅者subscriber去发出。
2:默认一个信号都是冷信号,就算是值改变了,但你没有订阅这个信号的话它也不会触发的,只有订阅了这个信号,这个信号才会变为热信号,值改变了才会触发。
二:RACSubject(信号提供者)它自己可以充当信号,又能发送信号。
RACReplaySubject (信号重复提供者)它是RACSubject的子类。
RACSubject * subject = [RACSubject subject]; // 自己订阅了信号 [subject subscribeNext:^(id x) { NSLog(@"第一个订阅者%@",x); }]; [subject subscribeNext:^(id x) { NSLog(@"第二个订阅者%@",x ); }]; // 自己发送了信号 [subject sendNext:@"520"];
XCode打印:
2016-08-09 15:41:44.464 RaectiveCocoaTest[23130:189079] 第一个订阅者520
2016-08-09 15:41:44.464 RaectiveCocoaTest[23130:189079] 第二个订阅者520
// 1.创建信号 RACReplaySubject *replaySubject = [RACReplaySubject subject]; // 2.发送信号 [replaySubject sendNext:@11]; [replaySubject sendNext:@22]; // 3.订阅信号 [replaySubject subscribeNext:^(id x) { NSLog(@"第一个订阅者接收到的数据%@",x); }]; // 订阅信号 [replaySubject subscribeNext:^(id x) { NSLog(@"第二个订阅者接收到的数据%@",x); }];
XCode打印:
2016-08-09 15:45:03.728 RaectiveCocoaTest[23370:191718] 第一个订阅者接收到的数据1
2016-08-09 15:45:03.728 RaectiveCocoaTest[23370:191718] 第一个订阅者接收到的数据2
2016-08-09 15:45:03.728 RaectiveCocoaTest[23370:191718] 第二个订阅者接收到的数据1
2016-08-09 15:45:03.729 RaectiveCocoaTest[23370:191718] 第二个订阅者接收到的数据2
解释:这里大家可以仔细看看,你不管第一次还是第二次订阅之后,它是把你以前发送的消息全都接受了一遍!而且它们俩的区别也要注意:
RACReplaySubject可以先发送信号,在订阅信号,RACSubject就不可以。
扩展:在上面学习的博客当中, RACSubject这个类是可以用来代替代理的,这里篇幅怕太长,影响大家阅读的内心,就不粘贴代码了,你可以去《最快让你上手ReactiveCocoa之基础篇》学习写一下,其实我建议大家已经掌握了他最基本的使用之后,可以自己尝试写一下,难度也不大。
三:RACSequence RAC中的集合类,可用来快速遍历数组,字典!
RACTuple RAC中的元组类,类似NSArray,用来包装值。看下面简单的使用。
先说说这个 RACSequence的简单使用;
//遍历数组 NSArray *numbers = @[@1,@2,@3,@4]; // 这里其实是三步 // 第一步: 把数组转换成集合RACSequence numbers.rac_sequence // 第二步: 把集合RACSequence转换RACSignal信号类,numbers.rac_sequence.signal // 第三步: 订阅信号,激活信号,会自动把集合中的所有值,遍历出来。 [numbers.rac_sequence.signal subscribeNext:^(id x) { NSLog(@"%@",x); }];
XCode打印
2016-08-09 16:24:55.445 RaectiveCocoaTest[25803:220322] 1
2016-08-09 16:24:55.446 RaectiveCocoaTest[25803:220322] 2
2016-08-09 16:24:55.446 RaectiveCocoaTest[25803:220322] 3
2016-08-09 16:24:55.446 RaectiveCocoaTest[25803:220322] 4
// 遍历字典,遍历出来的键值对会包装成RACTuple(元组对象 NSDictionary *dict = @{@"name":@"张旭",@"age":@24}; [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) { // RACTuple 就是一个元组,元组的概念在Swift有专门的介绍,没掌握的可以自己上网查一下! NSLog(@"RACTuple = %@",x); // 解包元组,会把元组的值,按顺序给参数里面的变量赋值 RACTupleUnpack(NSString *key,NSString *value) = x; // 相当于以下写法 // NSString *key = x[0]; // NSString *value = x[1]; NSLog(@"%@ %@",key,value); }];
XCode打印:
2016-08-09 16:12:21.204 RaectiveCocoaTest[25041:211762] RACTuple = <RACTuple: 0x7f9703d17860> (
name,
"\U5f20\U65ed"
)
2016-08-09 16:12:21.205 RaectiveCocoaTest[25041:211762] name 张旭
2016-08-09 16:12:21.206 RaectiveCocoaTest[25041:211762] RACTuple = <RACTuple: 0x7f9703e0ae60> (
age,
24
)
2016-08-09 16:12:21.206 RaectiveCocoaTest[25041:211762] age 24
解释:上面的注释里面解释就写得和很清楚了,就不在下面单独作解释了。
四:RACCommand
RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程。
使用场景:监听按钮点击,网络请求
五 RACMulticastConnection
用于当一个信号,被多次订阅时,为了保证创建信号时,避免多次调用创建信号中的block,造成副作用,可以使用这个类 处理。
这两部分的内容自己还没好好研究,后面会补充。需要可以先去前面看看。
ReactiveCocoa常见的方法:
1 代替代理: rac_signalForSelector
:用于替代代理。
2 代替KVO : rac_valuesAndChangesForKeyPath
:用于监听某个对象的属性改变。
3 监听事件: rac_signalForControlEvents
:用于监听某个事件。
4 代替通知: rac_addObserverForName
:用于监听某个通知。
5 监听文本框文字改变: rac_textSignal
:只要文本框发出改变就会发出这个信号。
6 处理当界面有多次请求时,需要都获取到数据时,才能展示界面;rac_liftSelector:withSignalsFromArray:Signals
:当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法。
使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。
上面这部分是由代码示例的,我学习的博客作者是写了的,大家可以去看看学习一下。
学习链接给大家: