首先看一下打算介绍的知识点:
知识点大纲
然后, 就开始One by One了:
(一) RAC的集合:
在RAC中, 也有一个元祖类, 叫做
RACTuple, 它完全可以当做OC的数组来用, 比如:
- (void)demo1 {
/* 元祖 */ RACTuple *tuple = [RACTuple tupleWithObjects:@"firstObject",@"secondObject",@1, nil]; NSString *string = tuple[1]; NSLog(@"%@", string);
}
你同样可以使用以下方法来创建一个元祖:
/// Creates a new tuple out of the array. Does not convert nulls to nils.+ (instancetype)tupleWithObjectsFromArray:(NSArray *)array;/// Creates a new tuple out of the array. If `convert` is YES, it also converts/// every NSNull to RACTupleNil.+ (instancetype)tupleWithObjectsFromArray:(NSArray *)array convertNullsToNils:(BOOL)convert;/// Creates a new tuple with the given objects. Use RACTupleNil to represent/// nils.+ (instancetype)tupleWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;
在这里我还是要推荐下我自己建的iOS开发学习群:680565220,群里都是学ios开发的,如果你正在学习ios ,小编欢迎你加入,今天分享的这个案例已经上传到群文件,大家都是软件开发党,不定期分享干货(只有iOS软件开发相关的),包括我自己整理的一份2018最新的iOS进阶资料和高级开发教程
元祖完全可以当做数组来使用, 你也可以通过下标来取出元祖中的数据.
在RAC中, 还有一个非常重要的集合类, 那就是
RACSequence, 且看:
- (void)demo2 { NSArray *array = @[@"jack", @"rose", @"james"];
[array.rac_sequence.signal subscribeNext:^(id _Nullable x) { NSLog(@"%@", [NSThread currentThread]); NSLog(@"%@", x);
}];
}
遍历一个数组, 打印的结果是:
数组遍历打印结果
可以看到的是: 数组中的元素被一一打印了, 值得注意的是: 这个打印的过程是在子线程调用的, 因为:
+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority name:(NSString *)name { return [[RACTargetQueueScheduler alloc] initWithName:name targetQueue:dispatch_get_global_queue(priority, 0)];
}
在这个方法的调用中, 使用了全局并发队列.
同样的, 还有字典的遍历:
- (void)demo3 {
NSDictionary *dict = @{
@"name" : @"jack",
@"age" : @18,
};
[dict.rac_sequence.signal subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"%@", x);
}];}
可以看到打印结果是打印了两个元祖类型的对象:
打印了两个元祖类型的对象
那么, 如何将这个元祖类型的对象转化成字典的键值对一一输出呢? 这里就需要用到一个功能强大的宏, 在RAC中, 有很多很强大的宏, 这个宏是这样的:RACTupleUnpack(...)
我们将需要解析的元祖赋值给这个宏, 同时, 将要解析的key值和value值做为宏的参数, 如下面的代码所示, 我们就能拿到字典的键值对了:
- (void)demo3 {
NSDictionary *dict = @{
@"name" : @"jack",
@"age" : @18,
};
[dict.rac_sequence.signal subscribeNext:^(RACTuple * _Nullable x) {
RACTupleUnpack(NSString *key, NSString *value) = x;
NSLog(@"%@----%@",key,value);
}];}
还有一点需要单独拿出来讲的就是利用RAC进行字典转模型. RAC提供了一个方法, 可以直接将字典数组映射成模型数组:
- (void)demo4 { NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:@"网页链接] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:NULL]; NSArray *infoArr = [[array.rac_sequence.signal map:^id _Nullable(NSDictionary *value) { return [KFCFood kfcFoodWithDictionary:value];
}] toArray]; NSLog(@"%@", infoArr);
}] resume];
}
当我们拿到服务器返回的响应体数据时, 利用json反序列化得到一个字典数组, 然后将数组转化成RACSequence对象,利用其signal属性进行映射, 再调用toArray方法就可以拿到装满模型对象的数组了:
模型数组
(二) RAC基本用法:
代替代理:
需求
假设有如上的需求, 我们一般使用代理来完成. 那么现在不用了, RAC很容易就能解决这个问题:
#import "YFSmallView.h"@implementation YFSmallView- (IBAction)greenButtonDidClick:(UIButton *)sender { NSLog(@"绿色按钮被点击了");
}@end
我在蓝色View内部定义一个处理点击事件的方法, 然后在控制器中, 响应这个方法产生一个信号, 然后订阅信号, 打印结果是一个元祖:
- (void)demo1 {
SEL sel = NSSelectorFromString(@"greenButtonDidClick:");
[[_blueView rac_signalForSelector:sel] subscribeNext:^(id _Nullable x) {
NSLog(@"%@" ,x);
}];
}
代替代理
我们可以看到的是:元祖里面保存的是响应的方法的参数, 那么我们可以用解包的方法, 将参数提取出来:
- (void)demo1 {
SEL sel = NSSelectorFromString(@"greenButtonDidClick:");
[[_blueView rac_signalForSelector:sel] subscribeNext:^(id _Nullable x) {
RACTupleUnpack(UIButton *sender) = x;
self.view.backgroundColor = sender.backgroundColor; }];}
通过这个, 我们能够拿到参数sender, 将sender的背景色赋值给控制器view :
运行结果
代替KVO:
/****************** -------- 代替KVO -------- ******************/- (void)demo2 {
[_blueView rac_observeKeyPath:@"frame" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) { NSLog(@"%@----%@", value, change);
}];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { static int x = 50;
x++;
_blueView.frame = CGRectMake(x, 50, 100, 100);
}
每点击屏幕就改变_blueView的值, 这时候, 就能够监听的到, 并且在block中进行逻辑处理, 参数value就是当前的keyPath属性对应的值, 参数change是一个字典,
打印结果
不过, 有更方便的监听方法:
[[_blueView rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
此时, 打印的x的值是当前属性的值.
监听事件:
以前, 我们监听按钮的点击事件, 我们得这么写代码:
- (void)demo3 {
[_blueButton addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonClick:(UIButton *)sender {
NSLog(@"点击了蓝色按钮+++%@", sender);
}
这样的不好的地方是, 业务逻辑被分割到了另外的地方,显得不统一, 而使用RAC的方法, 我们将逻辑直接写在block代码块里面, 这样可读性更强,使用更方便:
/****************** -------- 监听事件 -------- ******************/- (void)demo3 {
[[_blueButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"点击了蓝色按钮---%@", x);
}];
}
代替通知:
/****************** -------- 代替通知 -------- ******************/- (void)demo4 {
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"%@", x);
}];
}
block中打印的就是通知本身:
通知信息
监听文本框
/****************** -------- 监听文本框 -------- ******************/- (void)demo5 {
[self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
_textLabel.text = x;
}];
}
实现效果:
监听文本框实现效果
(三) 利用RAC定时器创建制作一个发送验证码的小demo
发送验证码是很常见的需求, 点击发送之后, 开始60秒倒计时, 此时按钮不能点击, 且文字变成灰色, 等到60秒时间到后, 便可以重新发送.一般情况下, 我们会用NSTimer, 但RAC为我们提供了更好的定时器方法:
+ (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler;
需要注意的是, 我们必须在主线程更新UI, 所以scheduler必须是主线程的scheduler, 使用[RACScheduler mainThreadScheduler]这个单例对象作为参数. 主要的代码如下:
self.disposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) { _time--; if (_time > 0) { _sendLabel.text = [NSString stringWithFormat:@"已发送,请等待%@秒", @(_time)]; _sendLabel.textColor = [UIColor lightGrayColor];
[_sendLabel removeGestureRecognizer:tap];
}else { _sendLabel.text = @"重新发送"; _sendLabel.textColor = [UIColor whiteColor];
[_sendLabel addGestureRecognizer:tap];
[_disposable dispose]; _time = 10;
}
}];
实现效果:
发送验证码实现效果
大神的搬砖者 想交流学习 需要资料视频的加群:680565220