写点什么

ReactiveCocoa - iOS 开发的新框架

  • 2014-02-11
  • 本文字数:3322 字

    阅读完需:约 11 分钟

ReactiveCocoa (其简称为 RAC)是由 Github 开源的一个应用于 iOS 和 OS X 开发的新框架。RAC 具有函数式编程和响应式编程的特性。它主要吸取了.Net 的 Reactive Extensions 的设计和实现。本文将详细介绍该框架试图解决什么问题,以及其用法与特点。

ReactiveCocoa 试图解决什么问题

经过一段时间的研究,我认为 ReactiveCocoa 试图解决以下 3 个问题:

  1. 传统 iOS 开发过程中,状态以及状态之间依赖过多的问题
  2. 传统 MVC 架构的问题:Controller 比较复杂,可测试性差
  3. 提供统一的消息传递机制

传统 iOS 开发过程中,状态以及状态之间依赖过多的问题

我们在开发 iOS 应用时,一个界面元素的状态很可能受多个其它界面元素或后台状态的影响。

例如,在用户帐户的登录界面,通常会有 2 个输入框(分别输入帐号和密码)和一个登录按钮。如果我们要加入一个限制条件:当用户输入完帐号和密码,并且登录的网络请求还未发出时,确定按钮才可以点击。通常情况下,我们需要监听这两个输入框的状态变化以及登录的网络请求状态,然后修改另一个控件的enabled状态。

传统的写法如下(该示例代码修改自 ReactiveCocoa 官网 ) :

复制代码
static void *ObservationContext = &ObservationContext;
(void)viewDidLoad {
[super viewDidLoad];
[LoginManager.sharedManager addObserver:self
forKeyPath:@"loggingIn"
options:NSKeyValueObservingOptionInitial
context:&ObservationContext];
[self.usernameTextField addTarget:self action:@selector(updateLogInButton)
forControlEvents:UIControlEventEditingChanged];
[self.passwordTextField addTarget:self action:@selector(updateLogInButton)
forControlEvents:UIControlEventEditingChanged];
}
- (void)updateLogInButton {
BOOL textFieldsNonEmpty = self.usernameTextField.text.length > 0
&& self.passwordTextField.text.length > 0;
BOOL readyToLogIn = !LoginManager.sharedManager.isLoggingIn && !self.loggedIn;
self.logInButton.enabled = textFieldsNonEmpty && readyToLogIn;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if (context == ObservationContext) {
[self updateLogInButton];
} else {
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}

RAC 通过引入信号(Signal)的概念,来代替传统 iOS 开发中对于控件状态变化检查的代理(delegate)模式或 target-action 模式。因为 RAC 的信号是可以组合(combine)的,所以可以轻松地构造出另一个新的信号出来,然后将按钮的enabled状态与新的信号绑定。如下所示:

复制代码
RAC(self.logInButton, enabled) = [RACSignal
combineLatest:@[
self.usernameTextField.rac_textSignal,
self.passwordTextField.rac_textSignal,
RACObserve(LoginManager.sharedManager, loggingIn),
RACObserve(self, loggedIn)
] reduce:^(NSString *username, NSString *password, NSNumber *
loggingIn, NSNumber *loggedIn) {
return @(username.length > 0 && password.length > 0 && !
loggingIn.boolValue && !loggedIn.boolValue);
}];

可以看到,在引入 RAC 之后,以前散落在action-target或 KVO 的回调函数中的判断逻辑被统一到了一起,从而使得登录按钮的enabled状态被更加清晰地表达了出来。

除了组合(combine)之外,RAC 的信号还支持链式(chaining)和过滤(filter),以方便将信号进行进一步处理。

试图解决 MVC 框架的问题

对于传统的 Model-View-Controller 的框架,Controller 很容易变得比较庞大和复杂。由于 Controller 承担了 Model 和 View 之间的桥梁作用,所以 Controller 常常与对应的 View 和 Model 的耦合度非常高,这同时也造成对其做单元测试非常不容易,对 iOS 工程的单元测试大多都只在一些工具类或与界面无关的逻辑类中进行。

RAC 的信号机制很容易将某一个 Model 变量的变化与界面关联,所以非常容易应用 Model-View-ViewModel 框架。通过引入 ViewModel 层,然后用 RAC 将 ViewModel 与 View 关联,View 层的变化可以直接响应 ViewModel 层的变化,这使得 Controller 变得更加简单,由于 View 不再与 Model 绑定,也增加了 View 的可重用性。

因为引入了 ViewModel 层,所以单元测试可以在 ViewModel 层进行,iOS 工程的可测试性也大大增强了。InfoQ 也曾撰文介绍过 MVVM:《MVVM 启示录》

统一消息传递机制

iOS 开发中有着各种消息传递机制,包括 KVO、Notification、delegation、block 以及 target-action 方式。各种消息传递机制使得开发者在做具体选择时感到困惑,例如在 objc.io 上就有专门撰文破船的翻译 ),介绍各种消息传递机制之间的差异性。

RAC 将传统的 UI 控件事件进行了封装,使得以上各种消息传递机制都可以用 RAC 来完成。示例代码如下:

复制代码
// KVO
[RACObserve(self, username) subscribeNext:^(id x) {
NSLog(@" 成员变量 username 被修改成了:%@", x);
}];
// target-action
self.button.rac_command = [[RACCommand alloc] initWithSignalBlock:
^RACSignal *(id input) {
NSLog(@" 按钮被点击 ");
return [RACSignal empty];
}];
// Notification
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(keyboardDidChangeFrameNotificationHandler:)
name:UIKeyboardDidChangeFrameNotification object:nil];

RAC 的RACSignal 类也提供了createSignal方法来让用户创建自定义的信号,如下代码创建了一个下载指定网站内容的信号。

复制代码
(RACSignal *)urlResults {
return [RACSignal createSignal:^RACDisposable *(id<racsubscriber> subscriber) { NSError *error; NSString *result = [NSString stringWithContentsOfURL: [NSURL URLWithString:@"http://www.devtang.com"] encoding:NSUTF8StringEncoding error:&error]; NSLog(@"download"); if (!result) { [subscriber sendError:error]; } else { [subscriber sendNext:result]; [subscriber sendCompleted]; } return [RACDisposable disposableWithBlock:^{ NSLog(@"clean up"); }]; }]; }</racsubscriber>

如何使用 ReactiveCocoa

ReactiveCocoa 可以在 iOS 和 OS X 的应用开发中使用,对于 iOS 开发者,可以将 RAC 源码下载编译后,使用编译好的libReactiveCocoa-iOS.a文件。

开发者也可以用 CocoaPods 来设置目标工程对 ReactiveCocoa 的依赖,只需要编辑 Podfile 文件,增加如下内容即可:

复制代码
pod 'ReactiveCocoa', ‘2.0'

ReactiveCocoa 的特点

RAC 在应用中大量使用了 block,由于 Objective-C 语言的内存管理是基于引用计数 的,为了避免循环引用问题,在block 中如果要引用self,需要使用 @weakify(self)@strongify(self)来避免强引用。另外,在使用时应该注意 block 的嵌套层数,不恰当的滥用多层嵌套 block 可能给程序的可维护性带来灾难。

RAC 的编程方式和传统的 MVC 方式差异巨大,所以需要较长的学习时间。并且,业界内对于 RAC 并没有广泛应用,这造成可供参考的项目和教程比较欠缺。另外,RAC 项目本身也还在快速演进当中,1.x 版本和 2.x 版本 API 改动了许多,3.0 版本也正在快速开发中,对它的使用也需要考虑后期的升级维护问题。

作为一个 iOS 开发领域的新开源框架,ReactiveCocoa 带来了函数式编程和响应式编程的思想,值得大家关注并且学习。

作者简介:

唐巧,资深 iOS 开发者和 Blogger,曾开发有道云笔记、猿题库和粉笔网的 iOS 客户端。他维护着 iOS 开发博客 http://www.devtang.com/ 和微信 iOS 开发公众账号 iosDevTips。唐巧在 2014 年 QCon 北京将进行一场 iOS 开发进阶的培训,介绍如何基于 CoreText 自己实现一个排版引擎

2014-02-11 00:2540783
用户头像

发布了 65 篇内容, 共 59.2 次阅读, 收获喜欢 23 次。

关注

评论

发布
暂无评论
发现更多内容

DeFi模式NFT游戏开发技术

薇電13242772558

NFT链游

【基础知识】PCB板上的字母数字是什么意思,代表哪些元器件?

华秋PCB

元器件 PCB PCB设计

百度工程师带你体验引擎中的nodejs

百度Geek说

JavaScript 前端 nodejs 12 月 PK 榜

RabbitMQ、RocketMQ、Kafka延迟队列实现

艾小仙

Java kafka RocketMQ RabbitMQ 延迟队列

四大领先优势加持,华为云会议服务更省心可靠!

路过的憨憨

会议云上开,华为云会议具有超高性价比

路过的憨憨

集结多种便捷功能,华为云会议让沟通简单化

路过的憨憨

【FAQ】在华为鸿蒙车机上集成华为帐号的常见问题总结

HarmonyOS SDK

HMS Core

数据价值深度挖掘,分析服务上线“探索”能力

HarmonyOS SDK

HMS Core

神州云科打出“组合拳”,双轨超高可用架构引领信创高质量发展

通明湖

以英雄之名为S9总决赛助攻!虎牙直播and华为云CDN,team work才会赢

爱尚科技

集结多种便捷功能,华为云会议大幅提升开会体验

路过的憨憨

用华为云桌面有多爽?问问设计师就知道了!

与时俱进的时代

在华为云桌面Workspace上,启泰智能工业设计效率翻倍

i生活i科技

不会PS怎么办?教你3种方法一键更换证件照背景色

互联网民工阿强

word ps 人像抠图 背景替换 证件照

华为云CDN节点扩增力度加大,构建全球智能边缘网络

爱尚科技

为什么说华为云CDN更值得选择?

爱尚科技

教你用JavaScript实现大转盘

小院里的霍大侠

JavaScript 初学者 入门实战

华为云CDN为芒果TV加速,打造丝滑“追剧观综”的观看体验

爱尚科技

华为云CDN通过全站加速引领网站性能全面优化

爱尚科技

远程灵活办公,华为云桌面了解一下

与时俱进的时代

云上智慧化办公,华为云桌面成为首选!

与时俱进的时代

论坛回顾|蚂蚁供应链安全建设实践

墨菲安全

软件供应链安全

QCN9074 802.11ax 4x4 MU-MIMO 6GHz wifi6E//qcn9072 qcn9024 qcn64 wallys

wallysmeng

QCN9074 QCN9024 QCN9072 qcn9064

华为云CDN助力企业用户体验全面优化,让企业“惠”加速

爱尚科技

阿里云助力抖音,为2022世界杯护航

云布道师

阿里云

schema设计与管理

刺猬

安全且高效!华为云会议全方位提升开会体验

路过的憨憨

双十二优惠,华为云桌面喊你来采购

与时俱进的时代

连续7年领跑!在华为云桌面,藏了一盘数字办公的大棋

i生活i科技

向云而行华为云桌面成数字办公首选

i生活i科技

ReactiveCocoa - iOS开发的新框架_QCon_唐巧_InfoQ精选文章