ReactiveCocoa

ReactiveCocoa简介

ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称,因此很多苹果框架喜欢以Cocoa结尾。

ReactiveCocoa作用

在我们iOS开发过程中,当某些事件响应的时候,需要处理某些业务逻辑,这些事件都用不同的方式来处理。

比如按钮的点击使用action,ScrollView滚动使用delegate,属性值改变使用KVO等系统提供的方式。

其实这些事件,都可以通过RAC处理

ReactiveCocoa为事件提供了很多处理方法,而且利用RAC处理事件很方便,可以把要处理的事情,和监听的事情的代码放在一起,这样非常方便我们管理,就不需要跳到对应的方法里。非常符合我们开发中高聚合,低耦合的思想。

编程思想

在开发中我们也不能太依赖于某个框架,否则这个框架不更新了,导致项目后期没办法维护,比如之前Facebook提供的Three20框架,在当时也是神器,但是后来不更新了,也就没什么人用了。因此我感觉学习一个框架,还是有必要了解它的编程思想。

先简单介绍下目前咱们已知的编程思想。

3.1 面向过程:处理事情以过程为核心,一步一步的实现。

3.2 面向对象:万物皆对象

3.3 链式编程思想:是将多个操作(多行代码)通过点号(.)链接在一起成为一句代码,使代码可读性好。a(1).b(2).c(3)

       链式编程特点:方法的返回值是block,block必须有返回值(本身对象),block参数(需要操作的值)

       代表:masonry框架。

3.4 响应式编程思想:不需要考虑调用顺序,只需要知道考虑结果,类似于蝴蝶效应,产生一个事件,会影响很多东西,这些事件像流一样的传播出去,然后影响结果,借用面向对象的一句话,万物皆是流。

       代表:KVO运用。

3.5 函数式编程思想:是把操作尽量写成一系列嵌套的函数或者方法调用。

       函数式编程特点:每个方法必须有返回值(本身对象),把函数或者Block当做参数,block参数(需要操作的值)block返回值(操作结果)

       代表:ReactiveCocoa。

ReactiveCocoa结合了几种编程风格:

函数式编程(Functional Programming)

响应式编程(Reactive Programming)

所以,你可能听说过ReactiveCocoa被描述为函数响应式编程(FRP)框架。

以后使用RAC解决问题,就不需要考虑调用顺序,直接考虑结果,把每一次操作都写成一系列嵌套的方法中,使代码高聚合,方便管理。

ReactiveCocoa的简单使用

   假设我们现在有个登录界面,需要输入username和password,然后点击signinButton,就能发起登录请求

[[[self.usernameTextField.rac_textSignal

  map:^id(NSString*text){

    return @(text.length);

  filter:^BOOL(NSNumber*length){

    return [length integerValue] > 3;

  subscribeNext:^(id x){

    NSLog(@"%@", x);

  }];

代码解析:这里给username编辑框的事件添加信号跟踪,将其映射为文本长度,超出长度3的输出日志。而且ReactiveCocoa的方法特性是都会返回类对象自身,方便链式调用。

插入介绍一下名词解释

信号(signal)— RACSignal类

本质:是一种流(流是值的序列化的抽象)

说明:一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据。

事件类型:

        next:发送数据到下一个管道

        error:发送数据失败

        completed:发送数据完成

用法:需要订阅不同的事件类型才能发挥作用,即调用下面这些实例方法

- (RACDisposable *)subscribeNext: (void (^)(id x))nextBlock;

- (RACDisposable *)subscribeError: (void (^)(NSError *error))errorBlock;

- (RACDisposable *)subscribeCompleted: (void (^)(void))completedBlock;

例子:ReactiveCocoa框架使用category来为很多基本UIKit控件添加signal。这样你就能给控件添加订阅了,text field的rac_textSignal就是这么来的。

[self.usernameTextField.rac_textSignal subscribeNext:^(id x) {

NSLog(@"x:%@",x);

}];

过滤 — Filter

说明:过滤信号,使用它可以获取满足条件的信号,举个形象的比喻就是一张可以自由设置网口大小的渔网,根据自己需要,对网口进行设置就可以捕到特定规格的鱼。

用法:在用户登录时,我们需要关心用户名长度是否符合要求,比如要求字符长度超过3,那么就可以使用Filter来达到这个目的,如下:

RACSignal *validUsernameSignal =

[self.usernameTextField.rac_textSignal filter:^BOOL(NSString *value) {

return value.length > 3;

}];

映射 — Map

说明:把源信号内容映射成新的内容,简单点说就是将数据改成自己想要的数据。

用法:还是用登录这个场景,我们需要关心用户名长度是否符合要求,比如字符长度超过3才进行下一步处理,如下:

RACSignal *usernameLengthSignal =

[[self.usernameTextField.rac_textSignal map:^id(NSString *value) {

return @(value.length);

}];

状态推导 — RAC()

说明:用于给某个对象的某个属性绑定。

用法:比如只要编辑框文字改变,就会修改label的文字

RAC(self.labelView,text) = _textField.rac_textSignal;

聚合信号

说明:聚合任意数量的信号,然后生成一个新的信号

用法:比如登录按钮只有当用户名和密码输入框的输入都有效时才能进行点击

// 创建聚合信号

RACSignal *signUpActiveSignal =

[RACSignal combineLatest: @[validUsernameSignal, validPasswordSinal]

reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){

return @([usernameValid boolValue] && [passwordValid boolValue]);

}];

参照下图,来控制界面对于用户操作的响应。

- (RACSignal *)signInSignal {

return[RACSignal createSignal:^RACDisposable *(id subscriber){

   [self.signInService 

     signInWithUsername:self.usernameTextField.text

               password:self.passwordTextField.text

               complete:^(BOOL success){

                    [subscriber sendNext: @(success)];

                    [subscriber sendCompleted];

     }];

returnnil;

}];

}

上面的方法创建了一个信号,使用用户名和密码登录并调用接口验证用户。现在分解来看一下。

上面的代码使用RACSignal的createSignal:方法来创建信号。方法的入参是一个block,这个block描述了这个信号。当这个信号有subscriber时,block里的代码就会执行。

block的入参是一个subscriber实例,它遵循RACSubscriber协议,协议里有一些方法来产生事件,你可以发送任意数量的next事件,或者用error\complete事件来终止。本例中,信号发送了一个next事件来表示登录是否成功,随后是一个complete事件。

这个block的返回值是一个RACDisposable对象,它允许你在一个订阅被取消时执行一些清理工作。当前的信号不需要执行清理操作,所以返回nil就可以了。

可以看到,把一个异步API用信号封装是多简单!      

外部订阅信号时,代码可以这样写:

[[[[self.signInButton

   doNext:^(id x){

     self.signInButton.enabled =NO;

     self.signInFailureText.hidden =YES;

   flattenMap:^id(id x){

     return[self signInSignal];

   subscribeNext:^(NSNumber*signedIn){

     self.signInButton.enabled =YES;

     BOOL success =[signedIn boolValue];

     self.signInFailureText.hidden = success;

     if(success){

       [self performSegueWithIdentifier: @"signInSuccess" sender:self];

     }

   }];

因为上面方法创建的是内部信号,需要使用flattenMap转换一下。可以看到doNext:是直接跟在按钮点击事件的后面。而且doNext: block并没有返回值。因为它是附加操作,并不改变事件本身。整个流程图如下: 

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容