ReactiveCocoa(其简称为RAC)是由Github开源的一个应用于iOS和OS X开发的新框架。
ReactiveCocoa简介
ReactiveCocoa是个注重结果的框架。先简单说一嘴响应式编程思想(Reactive Programming) ,你调用的顺序不需要考虑,因为你做任何的操作一定会对结果产生影响。然后就是函数式编程思想(Functional Programming),把代码高聚合起来写成一系列嵌套的函数或者方法调用。所以ReactiveCocoa又称之为函数响应式编程(FRP)框架。
RAC中的类解析
RACSiganl是个信号类,他初始化后需要Subscriber(订阅者)去订阅这个信号,如果没有订阅那么这个信号就是个冷信号,订阅过就是热信号。Signal可以被修改(map),过滤(filter),聚合(combine),串联(chain)。RACSignal类初始化方法如下:
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"调用此block");
[subscriber sendNext:@1];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// 执行完Block后,当前信号就不在被订阅了。
NSLog(@"信号被销毁");
}];
}];
//订阅信号,才会激活信号变成热信号。
[siganl subscribeNext:^(id x) {
NSLog(@"接收到数据:%@",x);
}];
[siganl subscribeNext:^(id x) {
NSLog(@"再次收到数据:%@",x);
}];
可以看出来订阅一次信号就会先调用信号源一次。
写个登陆的demo:
需求:用户名,密码栏长度大于3,如果没有大于3两个控件背景颜色是黄色的而按钮是不可点击并且是灰色的。
1.首先把控件都写好(用户名,密码,登陆按钮)2个textField 1个button
//用户名信号
RACSignal *validUsernameSignal = [self.usernameTextField.rac_textSignal map:^id(NSString *text) {
return @(text.length>3);
}];
[[self.usernameTextField.rac_textSignal
filter:^BOOL(id value) {
NSString *text = value;
return text.length > 3;
}]
subscribeNext:^(id x) {
//符合条件后执行(即获得用户名)
NSLog(@"用户名%@", x);
}];
//监听密码信号
RACSignal *validPasswordSignal = [self.passwordTextField.rac_textSignal map:^id(NSString *text) {
return @(text.length>3);
}];
//监听validUsernameSignal(用户名信号)返回值来改变用户名背景色
RAC(self.usernameTextField,backgroundColor) = [validUsernameSignal map:^id(NSNumber *passwordValid) {
return [passwordValid boolValue] ? [UIColor clearColor] : [UIColor yellowColor];
}];
//同上
RAC(self.passwordTextField,backgroundColor) = [validPasswordSignal map:^id(NSNumber *passwordValid) {
return [passwordValid boolValue] ? [UIColor clearColor] : [UIColor yellowColor];
}];
//联合用户名和密码信号
RACSignal *signUpActiveSignal = [RACSignal combineLatest:@[validPasswordSignal,validUsernameSignal]
reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){
return @([usernameValid boolValue] && [passwordValid boolValue]);
}];
//监听联合的信号并改变按钮的颜色
[signUpActiveSignal subscribeNext:^(NSNumber *signupActive) {
self.signInButton.enabled = [signupActive boolValue];
}];
//监听按钮的轻拍
[[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]
//执行Next之前,会先执行这个doNext的Block
doNext:^(id x) {
self.signInButton.enabled = NO;
}]
//和map相比它的返回值是信号
flattenMap:^id(id x) {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//这个方法就是将文本框文字传进去看看是否匹配对应的用户名和密码 这个方法后面还有个带有BOOL参数的block,这个参数就是是否正确匹配用户名和密码 ,
[self.signInService
signInWithUsername:self.usernameTextField.text
password:self.passwordTextField.text
complete:^(BOOL success) {
//订阅者将这个布尔值发送出去,下面的subscribeNext方法就会收到这个参数并做一系列的处理(跳进下个页面)
[subscriber sendNext:@(success)];
[subscriber sendCompleted];
}];
return nil;
}];;
}]
subscribeNext:^(NSNumber *signedIn) {
self.signInButton.enabled = YES;
BOOL success = [signedIn boolValue];
if (success) {
//进入下个页面
[self performSegueWithIdentifier:@"signinsuccess" sender:self];
}
}];