ReactiveCocoa - iOS开发的新框架
2015-03-03 11:11
295 查看
什么是ReactiveCocoa
ReactiveCocoa(其简称为RAC)是由Github 开源的一个应用于iOS和OSX开发的新框架。RAC具有函数式编程和响应式编程的特性。它主要吸取了.Net的 Reactive Extensions的设计和实现。
ReactiveCocoa试图解决什么问题
经过一段时间的研究,我认为ReactiveCocoa试图解决以下3个问题:传统iOS开发过程中,状态以及状态之间依赖过多的问题
传统MVC架构的问题:Controller比较复杂,可测试性差
提供统一的消息传递机制
传统iOS开发过程中,状态以及状态之间依赖过多的问题
我们在开发iOS应用时,一个界面元素的状态很可能受多个其它界面元素或后台状态的影响。例如,在用户帐户的登录界面,通常会有2个输入框(分别输入帐号和密码)和一个登录按钮。如果我们要加入一个限制条件:当用户输入完帐号和密码,并且登录的网络请求还未发出时,确定按钮才可以点击。通常情况下,我们需要监听这两个输入框的状态变化以及登录的网络请求状态,然后修改另一个控件的
enabled状态。
传统的写法如下(该示例代码修改自ReactiveCocoa官网 ) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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]; } } |
enabled状态与新的信号绑定。如下所示:
1 2 3 4 5 6 7 8 9 | 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); }]; |
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来完成。示例代码如下:
1 2 3 4 5 6 7 8 910 | // 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] rac_addObserverForName:UIKeyboardDidChangeFrameNotification object:nil] subscribeNext:^(id x) { NSLog(@"键盘Frame改变"); } ]; // Delegate [[self rac_signalForSelector:@selector(viewWillAppear:)] subscribeNext:^(id x) { debugLog(@"viewWillAppear方法被调用 %@", x); }]; |
RACSignal类也提供了
createSignal方法来让用户创建自定义的信号,如下代码创建了一个下载指定网站内容的信号。
1 2 3 4 5 6 7 8 910 | -(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"); }]; }]; } |
如何使用ReactiveCocoa
ReactiveCocoa可以在iOS和OS X的应用开发中使用,对于iOS开发者,可以将RAC源码下载编译后,使用编译好的libReactiveCocoa-iOS.a文件。
开发者也可以用CocoaPods来设置目标工程对ReactiveCocoa的依赖,只需要编辑Podfile文件,增加如下内容即可:
1 | pod 'ReactiveCocoa' |
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带来了函数式编程和响应式编程的思想,值得大家关注并且学习。
一些学习资源
博客&教程
http://spin.atomicobject.com/2014/02/03/objective-c-delegate-pattern/http://blog.bignerdranch.com/4549-data-driven-ios-development-reactivecocoa/
http://en.wikipedia.org/wiki/Functional_reactive_programming
http://www.teehanlax.com/blog/reactivecocoa/
http://www.teehanlax.com/blog/getting-started-with-reactivecocoa/
http://nshipster.com/reactivecocoa/
http://cocoasamurai.blogspot.com/2013/03/basic-mvvm-with-reactivecocoa.html
http://iiiyu.com/2013/09/11/learning-ios-notes-twenty-eight/
https://speakerdeck.com/andrewsardone/reactivecocoa-at-mobidevday-2013
http://msdn.microsoft.com/en-us/library/hh848246.aspx
http://www.itiger.me/?p=38
http://blog.leezhong.com/ios/2013/12/27/reactivecocoa-2.html
https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/FrameworkOverview.md
http://www.haskell.org/haskellwiki/Functional_Reactive_Programming
http://blog.zhaojie.me/2009/09/functional-reactive-programming-for-csharp.html
代码
https://github.com/Machx/MVVM-IOS-Examplehttps://github.com/ReactiveCocoa/RACiOSDemo
书籍
https://leanpub.com/iosfrp
视频
http://vimeo.com/65637501Posted
by 唐巧 Feb 11th,
2014 iOS
原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
相关文章推荐
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- REACTIVECOCOA - IOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的开源框架
- [转] iOS --- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- ReactiveCocoa - iOS开发的新框架
- iOS 6.0开发框架及功能更新小结
- HTML5在PhoneGap框架下开发IOS应用时常用操作和设置
- iOS开发视频教程—第四章Foudation框架介绍的源代码和课件下载
- 分享一个文档完整的超棒iOS开发框架(Frameworks) - NimbusKit
- iOS 6.0开发框架及功能更新小结
- iOS开发框架介绍(一)---iOS开发介绍