之前我们初步认识了 RAC 的设计思路跟实现方式, 现在我们再来看看如果使用它以及它能帮我们做什么
- 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.
官方是这样说的, RAC 为我们提供了简单便捷实现代理 / block 回调 / 事件 / 通知 / KVO 的方式
我们先看 RAC 如何帮助我们快速实现 KVO
首先我们新建一个 Student 类, 给它一个 age 的属性
- #import
- @interface Student: NSObject
- @property(nonatomic, strong) NSString * age;
- @end
下面我们看一个简单的如何使用 RAC 来实现 KVO
- Student * stu = [[Student alloc] init];
- // RAC KVO
- [RACObserve(stu, age) subscribeNext: ^(id _Nullable x) {
- NSLog(@"stu的age改变为: %@", x);
- }];
- stu.age = @"10";
运行看看:
- 2017 - 07 - 23 11 : 35 : 19.704 RAC[67362 : 13075201] stu的age改变为: (null) 2017 - 07 - 23 11 : 35 : 19.704 RAC[67362 : 13075201] stu的age改变为: 10
很方便对吧, 不用我们去 add observe, 不用出来观察事件, 也不用我们去移除关注
不过大家注意到了没, 这里添加关注后 block 立即执行了一次, 大家可以依据实际项目情况加个条件判断做处理.
这里其实 RAC 还为我们提供了除了 subscriber 以外的操作, 后面再介绍给, 现在我们主要先来看 RAC 是怎么替我们做 KVO 的
我们再看看 RAC 如何帮我们实现 target-action
我们创建一个项目, 在 controller 中添加一个 button, 然后给 button 添加一个点击事件
如果是常规写法的话, 在创建完 button 后创建一个点击响应方法, 然后通过 addTarget 把响应方法跟 button 及事件绑定到一起
大概类似这样:
- [button addTarget: self action: @selector(btnAction) forControlEvents: UIControlEventTouchUpInside];
- - (void) btnAction {
- NSLog(@"点击了按钮");
- }
在上一篇我们提到过这样的劣势, 当代码比较多的时候结构容易乱, 维护的时候也不好查找方法
我们看看 RAC 如何帮我们优雅的实现
RAC 为我们提供了 rac_signalForControlEvents 来处理 UIControllerEvent, 我们试试看
- [[button rac_signalForControlEvents: UIControlEventTouchUpInside] subscribeNext: ^(__kindof UIControl * _Nullable x) {
- NSLog(@"%@", x);
- }];
因为不知道这里的 x 是什么, 我们直接打印看看结果
- 2017 - 07 - 23 12 : 05 : 59.654 RAC[67611 : 13189769] 0x7f95e0d069f0;
- frame = (157 350.5; 100 35);
- opaque = NO;
- layer = 0x6080000269a0 >>
当我们点击按钮打印了上面这些, 是我们创建的 button 对象
那么加入需要点击的时候给 button 更换背景图片或者标题就可以在这里处理了, 我们用改变颜色举例
- [[button rac_signalForControlEvents: UIControlEventTouchUpInside] subscribeNext: ^(__kindof UIControl * _Nullable x) {
- x.backgroundColor = [UIColor redColor];
- }];
运行后, 就可以看到如果点击按钮背景就会变成红色, 如果有点击事件也可以放在这里
但如果点击后要处理的逻辑比较多, 代码超过三行建议大家单独写一个方法供调用, 以免破坏代码的结构
RAC 这样的使用方式, 让我的代码逻辑更加清晰紧凑了, 我们再看一个添加手势的例子
- UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] init];
- [[tap rac_gestureSignal] subscribeNext: ^(__kindof UIGestureRecognizer * _Nullable x) {
- NSLog(@"点击了屏幕");
- NSLog(@"x: %@", x);
- }];
- [self.view addGestureRecognizer: tap];
运行看看:
- 2017 - 07 - 23 12 : 15 : 59.246 RAC[67766 : 13231274]点击了屏幕2017 - 07 - 23 12 : 15 : 59.247 RAC[67766 : 13231274] x: 0x6000001a5160;
- state = Ended;
- view = 0x7fb932d03780 > ;
- target = <(action = sendNext: , target = 0x60800003a920 > ) >>
这里 x 是一个手势, 我们可以直接拿来使用, 比如我们改变下添加手势这个 view 的颜色
- UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] init];
- [[tap rac_gestureSignal] subscribeNext: ^(__kindof UIGestureRecognizer * _Nullable x) {
- NSLog(@"点击了屏幕");
- NSLog(@"x: %@", x);
- x.view.backgroundColor = [UIColor redColor];
- }];
- [self.view addGestureRecognizer: tap];
这样手势的初始化, 方法等等都在一起, 让代码一目了然
接下来我们看看 RAC 如何帮我们实现通知的
我们常规的通知应该是这样, 在要接收通知的地方添加关注通知并写上通知事件
- [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(notiAction) name: @"noti"object: nil];
- - (void) notiAction {
- NSLog(@"接到了通知");
- }
然后在对应的地方发送通知
- [[NSNotificationCenter defaultCenter] postNotificationName: @"noti"object: nil userInfo: nil];
RAC 会怎么帮我们实现呢
- [[[NSNotificationCenter defaultCenter] rac_addObserverForName: @"noti"object: nil] subscribeNext: ^(NSNotification * _Nullable x) {
- NSLog(@"接到了通知");
- }];
发送通知 iOS 已经很简单了, RAC 没有做重复工作但帮我们把添加关注通知的方法改进了, 可以让事件和通知关注在一起
这样接口就清晰了
那么 RAC 如果帮我们实现代理呢
我用 UIAlertView 给大家举个例子, 虽然苹果已经不推荐用这个 不过我们拿来当例子用用看
先写一个常规的 AlertView
- #import "ViewController.h"#import
- @interface ViewController()
- @end
- @implementation ViewController
- - (void) viewDidLoad { [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- UIAlertView * alertView = [[UIAlertView alloc] initWithTitle: @"RAC"message: @"RAC Delegate Test"delegate: self cancelButtonTitle: @"Cancel"otherButtonTitles: @"Ok", nil];
- [alertView show];
- }
- - (void) alertView: (UIAlertView * ) alertView clickedButtonAtIndex: (NSInteger) buttonIndex {
- if (buttonIndex == 0) {
- NSLog(@"点击了Cancel按钮");
- } else {
- NSLog(@"点击了Ok按钮");
- }
- }
- @end
初始化 alertView, 实现代理方法 这是我们常规的用法
那么我们再看看 RAC 如何做
- #import "ViewController.h"#import
- @interface ViewController()
- @end
- @implementation ViewController
- - (void) viewDidLoad { [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- UIAlertView * alertView = [[UIAlertView alloc] initWithTitle: @"RAC"message: @"RAC Delegate Test"delegate: self cancelButtonTitle: @"Cancel"otherButtonTitles: @"Ok", nil];
- [[self rac_signalForSelector: @selector(alertView: clickedButtonAtIndex: ) fromProtocol: @protocol(UIAlertViewDelegate)] subscribeNext: ^(RACTuple * _Nullable x) {
- NSLog(@"%@", x);
- }];
- [alertView show];
- }
- @end
RAC 为我们提供了一个 rac_signalForSelector: fromProtoc 方法帮我们实现代理
我们把 x 打印看看
- 2017 - 07 - 23 12 : 53 : 07.138 RAC[68380 : 13356332] 0x6080000149f0 > ("<UIAlertView: 0x7fc7dfc0c620; frame = (0 0; 0 0); layer = <CALayer: 0x6000002218a0>>", 1)
我们看看这个 RACTuple
- @interface RACTuple: NSObject
- @property(nonatomic, readonly) NSUInteger count;
- /// These properties all return the object at that index or nil if the number of
- /// objects is less than the index.
- @property(nonatomic, readonly, nullable) id first;@property(nonatomic, readonly, nullable) id second;@property(nonatomic, readonly, nullable) id third;@property(nonatomic, readonly, nullable) id fourth;@property(nonatomic, readonly, nullable) id fifth;@property(nonatomic, readonly, nullable) id last;
打印看看
- UIAlertView * alertView = [[UIAlertView alloc] initWithTitle: @"RAC"message: @"RAC Delegate Test"delegate: self cancelButtonTitle: @"Cancel"otherButtonTitles: @"Ok", nil];
- [[self rac_signalForSelector: @selector(alertView: clickedButtonAtIndex: ) fromProtocol: @protocol(UIAlertViewDelegate)] subscribeNext: ^(RACTuple * _Nullable x) {
- NSLog(@"%@", x);
- NSLog(@"first: %@", x.first);
- NSLog(@"second: %@", x.second);
- NSLog(@"third: %@", x.third);
- NSLog(@"fourth: %@", x.fourth);
- NSLog(@"fifth: %@", x.fifth);
- NSLog(@"last: %@", x.last);
- }];
- [alertView show];
结果为:
- 2017 - 07 - 23 16 : 29 : 26.089 RAC[68525 : 13409884] first: 0x7f814e604420;
- frame = (0 0; 0 0);
- layer = 0x60800003a3e0 >> 2017 - 07 - 23 16 : 29 : 26.090 RAC[68525 : 13409884] second: 1 2017 - 07 - 23 16 : 29 : 26.090 RAC[68525 : 13409884] third: (null) 2017 - 07 - 23 16 : 29 : 26.090 RAC[68525 : 13409884] fourth: (null) 2017 - 07 - 23 16 : 29 : 26.091 RAC[68525 : 13409884] fifth: (null) 2017 - 07 - 23 16 : 29 : 26.091 RAC[68525 : 13409884] last: 1
第一个是 alert 本身, 第二个是 index, 然后可以按我们的需要做处理了
另外要注意的是用 RAC 写代理是有局限的,它只能实现返回值为 void 的代理方法
先到这里, 现在我们知道我们能用 RAC 做什么了
下次我们继续看 RAC 的具体用法
来源: http://www.cnblogs.com/zhouxihi/p/7225341.html