ReactiveCocoa(其簡稱為RAC)是由Github開源的一個應(yīng)用于iOS和OS X開發(fā)的新框架掀抹。
ReactiveCocoa簡介
ReactiveCocoa是個注重結(jié)果的框架移国。先簡單說一嘴響應(yīng)式編程思想(Reactive Programming) 场晶,你調(diào)用的順序不需要考慮,因為你做任何的操作一定會對結(jié)果產(chǎn)生影響秒梅。然后就是函數(shù)式編程思想(Functional Programming)铐伴,把代碼高聚合起來寫成一系列嵌套的函數(shù)或者方法調(diào)用。所以ReactiveCocoa又稱之為函數(shù)響應(yīng)式編程(FRP)框架隅要。
RAC中的類解析
RACSiganl是個信號類,他初始化后需要Subscriber(訂閱者)去訂閱這個信號,如果沒有訂閱那么這個信號就是個冷信號董济,訂閱過就是熱信號步清。Signal可以被修改(map),過濾(filter)虏肾,聚合(combine)廓啊,串聯(lián)(chain)。RACSignal類初始化方法如下:
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"調(diào)用此block");
[subscriber sendNext:@1];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// 執(zhí)行完Block后封豪,當(dāng)前信號就不在被訂閱了崖瞭。
NSLog(@"信號被銷毀");
}];
}];
//訂閱信號,才會激活信號變成熱信號。
[siganl subscribeNext:^(id x) {
NSLog(@"接收到數(shù)據(jù):%@",x);
}];
[siganl subscribeNext:^(id x) {
NSLog(@"再次收到數(shù)據(jù):%@",x);
}];
執(zhí)行結(jié)果
可以看出來訂閱一次信號就會先調(diào)用信號源一次撑毛。
寫個登陸的demo:
需求:用戶名,密碼欄長度大于3,如果沒有大于3兩個控件背景顏色是黃色的而按鈕是不可點(diǎn)擊并且是灰色的藻雌。
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) {
//符合條件后執(zhí)行(即獲得用戶名)
NSLog(@"用戶名%@", x);
}];
//監(jiān)聽密碼信號
RACSignal *validPasswordSignal = [self.passwordTextField.rac_textSignal map:^id(NSString *text) {
return @(text.length>3);
}];
//監(jiān)聽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];
}];
//聯(lián)合用戶名和密碼信號
RACSignal *signUpActiveSignal = [RACSignal combineLatest:@[validPasswordSignal,validUsernameSignal]
reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){
return @([usernameValid boolValue] && [passwordValid boolValue]);
}];
//監(jiān)聽聯(lián)合的信號并改變按鈕的顏色
[signUpActiveSignal subscribeNext:^(NSNumber *signupActive) {
self.signInButton.enabled = [signupActive boolValue];
}];
//監(jiān)聽按鈕的輕拍
[[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]
//執(zhí)行Next之前胯杭,會先執(zhí)行這個doNext的Block
doNext:^(id x) {
self.signInButton.enabled = NO;
}]
//和map相比它的返回值是信號
flattenMap:^id(id x) {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//這個方法就是將文本框文字傳進(jìn)去看看是否匹配對應(yīng)的用戶名和密碼 這個方法后面還有個帶有BOOL參數(shù)的block驯杜,這個參數(shù)就是是否正確匹配用戶名和密碼 ,
[self.signInService
signInWithUsername:self.usernameTextField.text
password:self.passwordTextField.text
complete:^(BOOL success) {
//訂閱者將這個布爾值發(fā)送出去做个,下面的subscribeNext方法就會收到這個參數(shù)并做一系列的處理(跳進(jìn)下個頁面)
[subscriber sendNext:@(success)];
[subscriber sendCompleted];
}];
return nil;
}];;
}]
subscribeNext:^(NSNumber *signedIn) {
self.signInButton.enabled = YES;
BOOL success = [signedIn boolValue];
if (success) {
//進(jìn)入下個頁面
[self performSegueWithIdentifier:@"signinsuccess" sender:self];
}
}];