首页 > 编程知识 正文

iOS开发吧,ios开发基础知识

时间:2023-05-06 09:53:46 阅读:192122 作者:620

前言

上次接触ReactiveCocoa已经是三年前的事情了,最近公司开新项目了,我选择了MVVM+ReactiveCocoa架构,但是开始撸代码时发现RAC的接口好像变化很大,就再此学习一下。

框架引入 框架介绍

为了适应Objective-C、swift,ReactiveCocoa将代码拆分为四个库:ReactiveCocoa(集中于UI)、ReactiveSwift(swift版)、ReactiveObjC(OC版)、ReactiveObjCBridge(桥接)。

笔者新项目是以OC语言开发的,主要是讲解ReactiveObjC的使用

框架集成

笔者采用cocoapods来管理的,这里吐槽一下,ReactiveObjC的介绍页面居然都没有相应的集成语句。

pod 'ReactiveObjC' 主要的类

ReactiveCocoa主要由下面四个核心组件组成:

信号源:RACStream以及其子类订阅者:实现RACSubscriber协议的类调度器:RACScheduler以及其子类清洁工:RACDisposable以及其子类 信号源 RACStream

RACStream是一个抽象的类,任何对象的序列都可以理解为stream,在开发中我们一般是应用他的子类RACSignal、RACDisposable来进行开发。

RACSignal

RACSignal是我们开发中用的最多的一个类,RACSignal通常表示将要交付的数据,必须要有订阅者订阅后才可以发送数据。
RACSignal可以向订阅者发送以下三种不同的事件:

next 事件:该事件从流中提供一个新值,以传递给下一个订阅者。error 事件:该事件表示在信号结束前出现了错误,该事件可以携带一个NSError对象传递。completed事件:该事件表示信号已经完成,清洁工将开始销毁相应对象。
在日常开发中,一般是由一个或者多个next 事件,以及一个error 事件或者completed事件组成。 RACSignal提供了以下操作符(可理解为方法)方便我们处理信号:(该示例代码来自:ReactiveCocoa文档) +merge merge操作符:将多个信号集中到一个信号中,任意一个信号中有数据到达就触发一下。 RACSubject *letters = [RACSubject subject];RACSubject *numbers = [RACSubject subject];RACSignal *merged = [RACSignal merge:@[ letters, numbers ]];// Outputs: A 1 B C 2[merged subscribeNext:^(NSString *x) { NSLog(@"%@", x);}];[letters sendNext:@"A"];[numbers sendNext:@"1"];[letters sendNext:@"B"];[letters sendNext:@"C"];[numbers sendNext:@"2"]; -flatten: flatten操作符表示将多个信号集中到一个信号中,类似于merge RACSubject *letters = [RACSubject subject];RACSubject *numbers = [RACSubject subject];RACSignal *signalOfSignals = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) { [subscriber sendNext:letters]; [subscriber sendNext:numbers]; [subscriber sendCompleted]; return nil;}];RACSignal *flattened = [signalOfSignals flatten];// Outputs: A 1 B C 2[flattened subscribeNext:^(NSString *x) { NSLog(@"%@", x);}];[letters sendNext:@"A"];[numbers sendNext:@"1"];[letters sendNext:@"B"];[letters sendNext:@"C"];[numbers sendNext:@"2"]; -flattenMap:flattenMap操作符会创建多信号 RACSignal *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence.signal;[[letters flattenMap:^(NSString *letter) { return [database saveEntriesForLetter:letter]; }] subscribeCompleted:^{ NSLog(@"All database entries saved successfully."); }]; -then then操作符:创建并启动一个信号,执行后替换信号中的数据。 RACSignal *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence.signal;// The new signal only contains: 1 2 3 4 5 6 7 8 9//// But when subscribed to, it also outputs: A B C D E F G H IRACSignal *sequenced = [[letters doNext:^(NSString *letter) { NSLog(@"%@", letter); }] then:^{ return [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence.signal; }]; RACSubject

RACSubject是RACSignal的子类,可以创建一个可以手动控制的信号。

RACSubject提供了以下操作符(可理解为方法)方便我们处理信号 +combineLatest: combineLatest操作符:监视多个信号,然后在发生变化时从所有信号中发送最新的值。 RACSubject *letters = [RACSubject subject];RACSubject *numbers = [RACSubject subject];RACSignal *combined = [RACSignal combineLatest:@[ letters, numbers ] reduce:^(NSString *letter, NSString *number) { return [letter stringByAppendingString:number]; }];// Outputs: B1 B2 C2 C3[combined subscribeNext:^(id x) { NSLog(@"%@", x);}];[letters sendNext:@"A"];[letters sendNext:@"B"];[numbers sendNext:@"1"];[numbers sendNext:@"2"];[letters sendNext:@"C"];[numbers sendNext:@"3"]; -switchToLatest :switchToLatest操作符:只监控最新的sendNext发送的信号 RACSubject *letters = [RACSubject subject];RACSubject *numbers = [RACSubject subject];RACSubject *signalOfSignals = [RACSubject subject];RACSignal *switched = [signalOfSignals switchToLatest];// Outputs: A B 1 D[switched subscribeNext:^(NSString *x) { NSLog(@"%@", x);}];[signalOfSignals sendNext:letters];[letters sendNext:@"A"];[letters sendNext:@"B"];[signalOfSignals sendNext:numbers];[letters sendNext:@"C"];[numbers sendNext:@"1"];[signalOfSignals sendNext:letters];[numbers sendNext:@"2"];[letters sendNext:@"D"]; RACSequence

RACSequence表示序列的一个流数据,他为Cocoa中常见的集合都添加了-rac_sequence方法,并且提供了很多方法以便我们处理数据。

RACSequence提供了以下操作符(可理解为方法)方便我们处理数据: -map操作符 :遍历RACSequence中的数据并返回一个带有新数据的流。 RACSequence *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence;// Contains: AA BB CC DD EE FF GG HH IIRACSequence *mapped = [letters map:^(NSString *value) { return [value stringByAppendingString:value];}]; -filter操作符:一般是用来过滤数据的。 RACSequence *numbers = [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence;// Contains: 2 4 6 8RACSequence *filtered = [numbers filter:^ BOOL (NSString *value) { return (value.intValue % 2) == 0;}]; -concat操作符:将一个流包含的值添加到另外一个流中。 RACSequence *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence;RACSequence *numbers = [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence;// Contains: A B C D E F G H I 1 2 3 4 5 6 7 8 9RACSequence *concatenated = [letters concat:numbers];

-flatten操作符:将多个流的数据联合起来,并添加到一个新的流中。(此处可以多个流一起添加,此处的解释是RACSequence的应用,该方法在RACSignal中等同于merged)

-flattenMap操作符:flattenMap将一个流中的每个值转换成一个新的流,即-map:后执行-flatten操作。

订阅者 RACSubscriber协议

所有遵守了RACSubscriber协议的对象都可以成为订阅者(Subscriber),订阅者订阅信号后可以收到相应信号的所有事件。

订阅的方法如下:

// 仅订阅next类型事件:- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;// 仅订阅next和error类型事件:- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock;// 同时订阅三种类型事件:- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock;// 以及其他订阅方法- (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock;- (RACDisposable *)subscribeCompleted:(void (^)(void))completedBlock;- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock completed:(void (^)(void))completedBlock;- (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock; 调度器 RACScheduler

RACScheduler是基于GCD的串行队列实现的,用来统一调度消息订阅过程中的任务。

清洁工 RACDisposable

RACDisposable 常用于信号取消订阅时,当订阅取消时,他将执行一些资源回收的工作。

其他的方法 RACCommand

RACCommand常用于绑定UI界面触发命令,并执行相应信号。他为常见的UI控件添加了rac_command属性,并传递相应信号。

// target-actionself.button.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) { NSLog(@" 按钮被点击 "); return [RACSignal empty];}]; 添加KVO [RACObserve(self, username) subscribeNext:^(id x) { NSLog(@" 成员变量 username 被修改成了:%@", x);}]; 添加Notification [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidChangeFrameNotification object:nil] subscribeNext:^(id x) { NSLog(@" 键盘 Frame 改变 "); }]; 添加Delegate [[self rac_signalForSelector:@selector(viewWillAppear:)] subscribeNext:^(id x) { debugLog(@"viewWillAppear 方法被调用 %@", x);}]; 感受

本来今天的计划是阅读一下源码,然后写一篇有些技术深度的文章,但是在花了一天的时间,看完官方的introduction、Documentation,以及相关资料后,发现自己实在是能力有限,希望再接再厉。
不过在阅读英文文档的过程中,发现自己的英文阅读能力好像比自己想象中好很多。另外也发现了swift在行业的影响力越来越大了,后面看来要开始拥抱swift了。

推荐阅读

https://github.com/ReactiveCocoa/ReactiveObjC/tree/master/Documentation
https://github.com/ReactiveCocoa/ReactiveObjC#introduction
http://blog.leichunfeng.com/blog/2015/12/25/reactivecocoa-v2-dot-5-yuan-ma-jie-xi-zhi-jia-gou-zong-lan/
https://www.jianshu.com/p/596e2dac20fb
https://www.jianshu.com/p/4e3dd049cfc8

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。