ReactiveCocoa 入门学习 (一)
引言
现在由于需求的不断发展,MVC这个经典的框架由于Controller的任务越来越多,显得"臃肿"了,网上又推出了新的框架,比如MVVM,ReactiveCocoa, 今天就来学一下ReactiveCocoa框架,看看响应式编程的效果
我是从ReactiveCocoa入门教程这篇文章上下载的Demo学习的,需要pod入ReactiveCocoa框架。
核心思想:
RAC为应用中发生的不同事件流提供了一个标准接口。在ReactiveCocoa术语中这个叫做信号(signal),由RACSignal类表示。
示例使用:
导入库后,就来到演示的登录界面的.m文件中,首先用框架自然导入其头文件。
1 #import "RWViewController.h" 2 #import "RWDummySignInService.h" 3 //导入ReactiveCocoa库的头文件 4 #import "ReactiveCocoa.h"
RAC中扩展了UITextField和UITextView类,使用rac_textSignal,就可以监听用户输入的text啦。 还可以设置过滤条件,比如在输入少于4为的时候不给于显示。
1 //监听textField 2 [self.usernameTextField.rac_textSignal subscribeNext:^(id x) { 3 NSLog(@"usernameTextField.text = %@", x); 4 }]; 5 6 //密码框添加过滤条件:少于4位时不显示,过滤掉 7 [[self.passwordTextField.rac_textSignal filter:^BOOL(id value) { 8 //接受用户的输入密码 9 NSString * text = value; 10 return text.length > 3; 11 }] subscribeNext:^(id x) { 12 NSLog(@"filterStr = %@", x); 13 }];
原文说:ReactiveCocoa框架使用category来为很多基本UIKit控件添加signal。这样你就能给控件添加订阅了,text field的rac_textSignal就是这么来的。
1 /** 2 * 过滤用户名 3 */ 4 - (void)filterRACSignalTest{ 5 6 RACSignal *usernameSourceSignal = self.usernameTextField.rac_textSignal; 7 8 // //对信号添加过滤的条件 9 // RACSignal *filteredUsername = [usernameSourceSignal filter:^BOOL(id value) { 10 // NSString *text = value; 11 // return text.length > 3; 12 // }]; 13 // 14 // //监听过滤后的用户名打印 15 // [filteredUsername subscribeNext:^(id x) { 16 // NSLog(@"filteredUsername = %@", x); 17 // }]; 18 19 //对信号添加过滤的条件 20 [[usernameSourceSignal filter:^BOOL(id value) { 21 NSString *text = value; 22 return text.length > 3; 23 }] subscribeNext:^(id x) { 24 NSLog(@"filteredUsername = %@", x); 25 }]; 26 27 }
流程借用一下原文的图:
使用subscriber来订阅需要监听对象的事件,RACSignal会发事件流给所对应的subscriber,目前总共有三种类型的事件:next、error、completed。一个signal在因error终止或者完成前,可以发送任意数量的next事件。
添加map,返回text的长度,map操作通过block改变了事件的数据:
1 [[[usernameSourceSignal map:^id(NSString *text) { 2 return @(text.length); 3 }] filter:^BOOL(NSNumber *length) { 4 return [length integerValue] > 3; 5 }] subscribeNext:^(id x) { 6 NSLog(@"lenth = %@", x); 7 }]; 8
可以使用map操作来把接收的对象转换成想要的类型 。
细看UITextView (RACSignalSupport) 分类中rac_textSignal的构造方法,使用block来回调,果然是响应式的。
1 - (RACSignal *)rac_textSignal { 2 @weakify(self); 3 RACSignal *signal = [[[[[RACSignal 4 defer:^{ 5 @strongify(self); 6 return [RACSignal return:RACTuplePack(self)]; 7 }] 8 concat:[self.rac_delegateProxy signalForSelector:@selector(textViewDidChange:)]] 9 reduceEach:^(UITextView *x) { 10 return x.text; 11 }] 12 takeUntil:self.rac_willDeallocSignal] 13 setNameWithFormat:@"%@ -rac_textSignal", self.rac_description]; 14 15 RACUseDelegateProxy(self); 16 17 return signal; 18 }
这是发送next事件部分~ 附上这一部分的Demo下载。