今天主要分享內(nèi)容:
- ReactiveCocoa簡單介紹
- 響應(yīng)式編程和函數(shù)編程的概述
- RACSignal 信號
- RACSignald訂閱過程
- First Demo
- Second Demo
- 參考鏈接
ReactiveCocoa
- GitHub mac 客戶端副產(chǎn)物
- FRP(響應(yīng)式函數(shù)編程)在cocoa框架的實現(xiàn)
- ReactiveCocoa可以對代理模式, target-action模式,鍵值對觀察(KVO)等進行替代
響應(yīng)式函數(shù)編程概述
ReactiveCocoa框架讓你可以在iOS應(yīng)用中使用響應(yīng)式函數(shù)編程(FRP)
- 命令式編程 VS 函數(shù)式編程 VS 響應(yīng)式編程(粗淺介紹)
int func(int x)
{
int result = 1;
for (int i = 1; i <=x; ++i)
{
result *= i;
}
} ```
命令式編程關(guān)心解決問題的步驟
你得把達到目的的步驟詳細的描述出來群叶,
然后交給機器去運行茂嗓。
需要管理非常多的中間狀態(tài)量刁赦,代碼繁雜嘹屯。
int func(int x)
{
if (x == 1) return 1;
return x * func(x - 1);
} ```
函數(shù)式編程關(guān)心數(shù)據(jù)的映射
這里的映射就是數(shù)學(xué)上「函數(shù)」的概念,
一種東西和另一種東西之間的對應(yīng)關(guān)系评肆。
沒有狀態(tài)量慢蜓,簡潔高效亿絮。
void test() {
int a = 5;
int b = 6;
int c = a + b;
int d = funAdd(&a , &b);//a b中的值
a = 10;
NSLog(@"%d",c);
} ```
響應(yīng)式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式岭粤。
在響應(yīng)式編程中d的值會隨著a或b的更新而更新惜索。
### RACSignal 信號
ReactiveCocoa四大核心組件構(gòu)成:
信號源:RACStream 及其子類;
訂閱者:RACSubscriber 的實現(xiàn)類及其子類绍在;
調(diào)度器:RACScheduler 及其子類门扇;
清潔工:RACDisposable 及其子類。
其中偿渡,信號源又是最核心的部分,其他組件都是圍繞它運作的霸奕。
ReactiveCocoa使用信號來代表異步事件溜宽,提供了一種統(tǒng)一的方式來處理所有異步的行為,包括代理方法质帅、block 回調(diào)适揉、target-action 機制、通知煤惩、KVO 等:
// 代理方法
[[self
rac_signalForSelector:@selector(webViewDidStartLoad:)
fromProtocol:@protocol(UIWebViewDelegate)]
subscribeNext:^(id x) {
// 實現(xiàn) webViewDidStartLoad: 代理方法
}];
// target-action
[[self.avatarButton
rac_signalForControlEvents:UIControlEventTouchUpInside]
subscribeNext:^(UIButton *avatarButton) {
// avatarButton 被點擊了
}];
// 通知
[[[NSNotificationCenter defaultCenter]
rac_addObserverForName:kReachabilityChangedNotification object:nil]
subscribeNext:^(NSNotification *notification) {
// 收到 kReachabilityChangedNotification 通知
}];
// KVO
[RACObserve(self, username) subscribeNext:^(NSString *username) {
// 用戶名發(fā)生了變化
}];
### RACSignald訂閱過程
// 創(chuàng)建信號 并發(fā)送信號
//使用RACSignal的createSignal:方法創(chuàng)建信號嫉嘀。描述這個信號的block是這個方法唯一的入?yún)ⅰ.斶@個信號有訂閱者的時候魄揉,block中的代碼就會執(zhí)行剪侮。
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendNext:@2];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"dispose");
}];
}];
// 訂閱信號
RACDisposable *disposable = [signal subscribeNext:^(id x) {
NSLog(@"next value is %@",x);
} error:^(NSError *error) {
NSLog(@"error -> %@",[error description]);
} completed:^{
NSLog(@"It finished success");
}];
[disposable dispose];
//ReactiveCocoa的信號(表現(xiàn)為RACSignal類)會向他的訂閱者們發(fā)送事件流。
//發(fā)送的事件分為三種類型:next洛退,error 和 completed瓣俯。
//一個信號在因為報錯或完成的終止前可以發(fā)送若干個事件。
### First Demo
實現(xiàn)一個登陸界面
![](http://upload-images.jianshu.io/upload_images/1292402-4ff2c2884df27598.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
要求:
1. User & Password不少于3位
2. 低于3位顯示紅色兵怯,正常顯示藍色
3. 登錄按鈕只有在用戶名和密碼都有效輸入時才能使用
Answer 1
//ReactiveCocoa框架使用category為很多標準的UIKit控件添加了信號
//可以對它們的各種事件進行訂閱
//1.創(chuàng)建信號
RACSignal *userName = [self.usernameTextField rac_textSignal];
//2.篩選
RACSignal *validUsername = [userName filter:^BOOL(id value) {
NSString *text = value;
return [self isValidUsername:text];
}];
//3.調(diào)用信號RACSignal的subscribeNext就能訂閱,
//subscribeNext:方法就提供了一個block彩匕,
//在每個next事件到達時執(zhí)行里面的代碼。
[validUsername subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
Answer 2
[[self.usernameTextField.rac_textSignal
map:^id(NSString *username) {
return [self isValidUsername:username] ? [UIColor whiteColor] : [UIColor redColor];
}]
subscribeNext:^(UIColor *color) {
self.usernameTextField.backgroundColor = color;
}];
[[self.passworkTextField.rac_textSignal
map:^id(NSString *password) {
return [self isValidUsername:password] ? [UIColor whiteColor] : [UIColor redColor];
}]
subscribeNext:^(UIColor *color) {
self.passworkTextField.backgroundColor = color;
}];```
Answer 3
//創(chuàng)建兩個發(fā)送布爾值的信號validUsernameSignal媒区、validPasswordSignal
//對用戶名和密碼的輸入進行驗證驼仪。
RACSignal *validUsernameSignal =
[self.usernameTextField.rac_textSignal
map:^id(NSString *text) {
return @([self isValidUsername:text]);
}];
RACSignal *validPasswordSignal =
[self.passworkTextField.rac_textSignal
map:^id(NSString *text) {
return @([self isValidPassword:text]);
}];
//信號合成
//接下來的任務(wù)就是合成這兩個信號掸犬,用以共同決定登錄按鈕是否可用
RACSignal *signUpActiveSignal =
[RACSignal combineLatest:@[validUsernameSignal, validPasswordSignal]
reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid) {
return @([usernameValid boolValue] && [passwordValid boolValue]);
}];
//上面的代碼使用combineLatest:reduce:方法 (RACSignal合成方法可以合成任意數(shù)量的信號)
//獲取validUsernameSignal和validPasswordSignal的最近一個信號值并組合成一個全新的信號。
//每當兩個源信號的其中一個發(fā)送新值绪爸,
//reduce里的block代碼塊就會執(zhí)行(reduce中 block的入?yún)⒑驮葱盘栆灰粚?yīng))
//其返回的值會作為合成信號的值發(fā)送出去湾碎。
//最后是訂閱
[signUpActiveSignal subscribeNext:^(NSNumber *signupActive) {
self.signinBnt.enabled = [signupActive boolValue];
}];
Second Demo
1.主動獲取數(shù)據(jù)并刷新TableView
2.根據(jù)搜索關(guān)鍵字獲取指定數(shù)據(jù),并刷新TableView毡泻;
Demo地址
參考鏈接
Reactive github
美團的幾篇博客
RACSignal的Subscription深入分析
raywenderlich 上的文章:
http://www.raywenderlich.com/62699/reactivecocoa-tutorial-pt1胜茧、http://www.raywenderlich.com/62796/reactivecocoa-tutorial-pt2、http://www.raywenderlich.com/74106/mvvm-tutorial-with-reactivecocoa-part-1仇味、http://www.raywenderlich.com/74131/mvvm-tutorial-with-reactivecocoa-part-2呻顽。