ReactiveCocoa 入门教程(一)

1.ReactiveCocoa简介


RAC 是一个 iOS 中的函数式响应式编程框架,是Github 在开发 GitHub for Mac 过程中的一个副产品,他提供了一系列用来组合和转换值流的 API,为事件的处理定义了一个标准接口,大大方便了开发者去管理各种事件的处理,结果就是开发者能从关注业务实现的细节上脱身,转变为开发者只需要关心业务本身就好了,是不是听起来很神奇的样子,接下来就让我们进入开发的另一片天空吧!

2.ReactiveCocoa作用


RAC关键解决的问题是开发中经常回见的“低聚合,高耦合”问题。

在RAC出现之前,我们编写iOS代码,大部分都是在响应一些事件:按钮点击、接收网络消息、属性变化等等。但处理事件的形式在苹果官方API中却有好几种:如target-action、代理方法、KVO、回调或其它。以上这几种,往往在一个项目中基本都会使用到,在不同的地方会出现很多处理事件的形式,这就带来了不能很好统一管理问题。因此,我们想,有没有一个统一管理的解决方案呢?这个方案又是怎样的呢?到这里ReactiveCocoa就该粉墨登场了,它出现的目的就是为了解决统一标准去管理代码中的事件。

3.编程思想


ReactiveCocoa结合了几种编程风格:

函数式编程(Functional Programming):使用高阶函数,例如函数用其他函数作为参数。

响应式编程(Reactive Programming):关注于数据流和变化传播。

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

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

4.底层原理


      1、运用的是Hook(钩子)思想,Hook是一种用于改变API(应用程序编程接口:方法)执行结果的技术.

      2、Hook用处:截获API调用的技术。

      3、Hook原理:在每次调用一个API返回结果之前,先执行你自己的方法,改变结果的输出。

5.常见类和常见功能


信号(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]);

}];

// 绑定按钮

[signUpActiveSignal subscribeNext:^(NSNumber *signupActive) {

@strongify(self)

self.signInButton.enabled = [signupActive boolValue];

}];

创建信号

说明:创建一个信号,用于执行信号中的Block,只要有订阅者,Block中的内容就会被执行。

用法:比如点击按钮进行登录时,就可以创建一个信号,然后进行订阅,然后执行登录的业务逻辑处理

// 创建信号

- (RACSignal *)signInSignal {

@weakify(self)

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

@strongify(self)

[self.signInService signInWithUsername:self.usernameTextField.text

password:self.passwordTextField.text

complete:^(BOOL success) {

[subscriber sendNext:@(success)];

// 必须创建完成时间

[subscriber sendCompleted];

}];

return nil;

}];

}

// 点击登录按钮

[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]

map:^id(id value) {

@strongify(self)

return [self signInSignal];

}] subscribeNext:^(id x) {

NSLog(@"Sign in result: %@", x);

}];

信号中的信号 — map —> flattenMap

说明:换句话说就是一个外部信号里面还有一个内部信号。

用法:比如上面这个栗子,订阅后发送的数据 x 类型最终还是信号,而不是创建信号时发送的NSNumber类型:

// 点击登录按钮(Map)

[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]

map:^id(id value) {

@strongify(self)

return [self signInSignal];

}] subscribeNext:^(id x) {

NSLog(@"Sign in result: %@", x);// X类型还是RACSignal

}];

// 点击登录按钮(FlattenMap)

[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]

flattenMap:^id(id value) {

@strongify(self)

return [self signInSignal];

}] subscribeNext:^(id x) {

NSLog(@"Sign in result: %@", x);// X类型是NSNumber

}];

FlatternMap和Map的区别:

FlatternMap中的Block返回信号。

Map中的Block返回对象。

开发中,如果信号发出的值不是信号,映射一般使用Map

开发中,如果信号发出的值是信号,映射一般使用FlatternMap

总结:signalOfsignals用FlatternMap。

添加附加操作(doNext:)

说明:执行Next之前,会先执行这个Block,简单说就是在一段逻辑执行前进行拦截,然后先执行一段特别操作,再操作接下来的逻辑

- (RACSignal *)doNext:(void (^)(id x))block

用法:还是拿登录的场景来说,当登录service正在校验用户名和密码时,登录按钮应该是不可点击的。这会防止用户多次执行登录操作。还有,如果登录失败了,用户再次尝试登录时,应该隐藏错误信息。

6.总结


ReactiveCocoa的核心就是信号,而它不过就是事件流,通过订阅将数据发送出去。以上就是本篇笔记的核心概念,哈哈,是不是很简单呢?

通过以上一些概念和使用场景,我们大概对RAC有了初步的认识。基础有了,接下来学习深入的知识点就容易多了。

参考

1、RayWenderlich ReactiveCocoa Tutorial – The Definitive Introduction: Part 1/2

2、iOS的函数响应型编程

3、MISSAJJ琴瑟静听( Swift 和 Objective-C )iOS 开发项目电子书

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

推荐阅读更多精彩内容