第四十五篇:ReactiveCocoaObjC使用
阿新 • • 發佈:2019-01-02
引導:首先如果要使用 ReactiveCocoaObjC 第三方框架就先需要匯入該框架,我匯入時使用了 cocoapods 匯入的,在 podfile 檔案中輸入以下的內空:
use_frameworks!
target 'ReactiveCocoaDome' do
pod 'AFNetworking', '~> 3.0.4'
pod 'ReactiveObjC', '~> 3.0.0'
end
1、RACSignal 先訂閱 再發送 (主執行緒中執行)
/**
1、RACSignal : 先訂閱 再發送(主執行緒中執行)
*/
-(void (^)(void))RACSignalDome
{
return ^{
/*
RACSignal : 只能訂閱且只有一個訂閱者subscriber,RACSignal 本身不能傳送訊號;在建立 RACSignal 的時候會自動建立一個 RACSubscriber 類的物件subscriber,subscriber 可以傳送訊號資訊;
*/
RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog (@"訊號 block , thread = %@",[NSThread currentThread]);
// 傳送訊號
[subscriber sendNext:@"RACSignalDome"];
// 呼叫該方法後會自動使用 disposableWithBlock()
[subscriber sendCompleted];
// 釋放
return [RACDisposable disposableWithBlock:^{
NSLog (@"disposableWithBlock , thread = %@",[NSThread currentThread]);
}];
}];
// 訂閱
// 當建立 signal 時的 subscriber 發出訊號改變 [subscriber sendNext:@"中國人民"] 就會呼叫 下面的 訂閱block , 當前最新版本與以往的不同,現在都是在主執行緒中執行 block
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"訂閱 block = %@ , thread = %@",x,[NSThread currentThread]);
} error:^(NSError * _Nullable error) {
NSLog(@"訂閱錯誤 = %@,thread = %@",error,[NSThread currentThread]);
} completed:^{
NSLog(@"完成訂閱 thread = %@",[NSThread currentThread]);
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext x = %@",x);
}];
};
}
2、RACSubject:先訂閱 再發送 (主執行緒中執行)
- 價值:可以用在代理上,引數就可以可區分呼叫哪一塊的程式碼
/**
2、RACSubject:先訂閱 再發送 (主執行緒中執行)
價值:可以用在代理上,引數可以用於區分呼叫哪一塊的程式碼
*/
-(void (^)(void))RACSubjectDome
{
return ^{
RACSubject * subject = [RACSubject subject];
// 其中所有的 block 都在 main 主執行緒中執行
// 訂閱
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext:x = %@ , thread = %@",x,[NSThread currentThread]);
}];
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext:x = %@ error completed , thread = %@",x,[NSThread currentThread]);
} error:^(NSError * _Nullable error) {
NSLog(@"error = %@ , thread = %@",error,[NSThread currentThread]);
} completed:^{
NSLog(@"completed ! , thread = %@",[NSThread currentThread]);
}];
// 傳送
[subject sendNext:@"RACSubjectDome"];
[subject sendCompleted];
};
}
3、RACReplaySubject先發送 再訂閱(主執行緒中執行)
- 這個比較 實用 ,可以在不知道什麼時候傳送訊號的情況下準確的接收到訊號
/**
3、先發送 再訂閱 (這個比較 實用 ,可以在不知道什麼時候傳送訊號的情況下準確的接收到訊號)(主執行緒中執行)
*/
-(void(^)(void))RACReplaySubjectDome
{
return ^{
// Capacity 事先預指訂閱的個數,裡面是動太陣列
RACReplaySubject * replaySubject = [RACReplaySubject replaySubjectWithCapacity:2];
// 傳送
[replaySubject sendNext:@"RACReplaySubjectDome 先發送 1"];
[replaySubject sendNext:@"RACReplaySubjectDome 先發送 2"];
[replaySubject sendCompleted];
// 訂閱
[replaySubject subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext:x = %@ error completed , thread = %@",x,[NSThread currentThread]);
} error:^(NSError * _Nullable error) {
NSLog(@"error = %@ , thread = %@",error,[NSThread currentThread]);
} completed:^{
NSLog(@"completed ! , thread = %@",[NSThread currentThread]);
}];
// 延時訂閱,一樣可以接收到訊號
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[replaySubject subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext: x = %@, thread = %@",x,[NSThread currentThread]);
}];
});
};
}
4、RACTuple :將陣列 或 字典等所有的內容可以用 元組 列出(非同步執行,開了新的執行緒)
/**
4、RACTuple :將陣列 或 字典等所有的內容可以用 元組 來列出(非同步執行,開了新的執行緒)
*/
-(void(^)(void))NSArrayAndNSDictionaryRACTupleDome
{
return ^{
// 1.把值包裝成 元組
RACTuple * tuple = RACTuplePack(@"abc",@"def",@"ghj");
// // 解析元組
// RACTupleUnpack(NSString * a , NSString * b , NSString * c) = tuple ;
NSLog(@"RACTuple 元組包裝: pack = %@ ",tuple);
// 2.NSDictionary 元組 , 將字典裡面的每一對 keyValue 列舉出來(開了一個新的執行緒,非同步列舉)
NSDictionary * dicTuple = @{@"name":@"Jakey" , @"age":@18 , @"student":@(YES)};
[dicTuple.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSString * key = [(RACTuple *)x objectAtIndex:0];
id value = [(RACTuple *)x objectAtIndex:1];
NSLog(@"NSDictionary 元組使用 = %@ , key = %@ , value = %@ , thread = %@",x,key,value,[NSThread currentThread]);
}completed:^{
NSLog(@"NSDictionary 元組使用 completed , thread = %@",[NSThread currentThread]);
} ];
// 3.NSArray 元組 ,將陣列內的所有資料列舉出來 (非同步列舉)
NSArray * array = @[@"klr",@"nop",@"rst"];
[array.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"NSArray 元組 x = %@ , thread = %@",x,[NSThread currentThread]);
}error:^(NSError * _Nullable error) {
NSLog(@"NSArray 元組 error = %@",error);
} completed:^{
NSLog(@"NSArray 元組 completed ,thread = %@",[NSThread currentThread]);
}];
// 4.非同步列出 陣列 或 字典 內容
NSArray * mapArray = [[array.rac_sequence map:^id _Nullable(id _Nullable value) {
NSLog(@"value = %@ , thread = %@",value,[NSThread currentThread]);
return [value stringByAppendingString:@" temp"];
}] array] ;
NSLog(@"===== %@", mapArray);
};
}
5、RACMulticastConnection :廣播連線(將 RACSignal 轉成 RACMulticastConnection , block 在 main 主執行緒執行)
/**
5、RACMulticastConnection :廣播連線(將 RACSignal 轉成 RACMulticastConnection , block 在 main 主執行緒執行)
*/
-(void(^)(void))RACMulticastConnectionDome
{
return ^{
// 不能解決 _view ( === self->_view , 這樣就無法解決強引用的問題)
// __weak typeof(self) weakSelf = self ;
// 無論哪種用法都可以解決強引用問題
@weakify(self);
RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// @weakify(self) 配套使用
@strongify(self);
NSLog(@"connection createSignal , thread = %@",[NSThread currentThread]);
[self loadDataFromNetwork:^(NSArray *dataArr) {
NSLog(@"loadDataFromNetwork block dataArr = %@ , thread = %@",dataArr , [NSThread currentThread]);
// 傳送訊號
[subscriber sendNext:dataArr];
[subscriber sendCompleted];
}];
return [RACDisposable disposableWithBlock:^{
NSLog(@"connection disposableWithBlock ,thread = %@",[NSThread currentThread]);
}];
}];
// // 直接訂閱
// [signal subscribeNext:^(id _Nullable x) {
//
// NSLog(@"subscribeNext x = %@ , thread = %@",x,[NSThread currentThread]);
//
// }];
// 將 signal 轉化成 connection
RACMulticastConnection * connection = [signal publish];
// 訂閱訊號
// RACSubject:RACSubscriber
[connection.signal subscribeNext:^(id _Nullable x) {
NSLog(@"commection x = %@ , thread = %@",x,[NSThread currentThread]);
}];
[connection.signal subscribeNext:^(id _Nullable x) {
NSLog(@"commection2 x = %@ , thread = %@",x,[NSThread currentThread]);
}];
// 連線
// RACSubject 訂閱 RACSignal
[connection connect];
};
}
// 網路資料載入方法
-(void)loadDataFromNetwork:(void(^)(NSArray * dataArr))resultBlock
{
NSLog(@"loadDataFromNetwork selector thread = %@",[NSThread currentThread]);
resultBlock(@[@"temp = 1" , @"temp = 2" , @"temp = 3"]);
}
6、RACCommand:處理事件的操作.(主執行緒中執行)
- (1) RACCommand : 內部必須返回 RACSignal
- (2) executionSignals : 訊號外的訊號
- (2.1) switchToLatest 最新發出來訊號的 RACSignal 型別
- (2.2) 能過 (2.1)的詮釋,那麼只要用 switchToLatest subscribeNext: 訂閱,就可以接收到發出來的訊號
- (3) 下面是執行的順序,用 (index)表示
- (4) execute:(id)input ; 該物件方法必須被呼叫(呼叫次數只有一次有效)才會執行一些相關操作,所有的 block 執行操作的 入口
/**
6、RACCommand:處理事件的操作.(主執行緒中執行)
(1) RACCommand : 內部必須返回 RACSignal
(2) executionSignals : 訊號外的訊號
(2.1) switchToLatest 最新發出來訊號的 RACSignal 型別
(2.2) 能過 (2.1)的詮釋,那麼只要用 switchToLatest subscribeNext: 訂閱,就可以接收到發出來的訊號
(3) 下面是執行的順序,用 (index)表示
(4) execute:(id)input ; 該物件方法必須被呼叫(呼叫次數只有一次有效)才會執行一些相關操作,所有的 block 執行操作的 入口
*/
-(void(^)(void))RACCommandDome
{
return ^{
RACCommand * command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
// input 即是執行 execute:(id)input; 傳進來的值 (3)
NSLog(@"init RACCommand block 被執行 initWithSignalBlock input = %@ , thread = %@",input,[NSThread currentThread]);
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// (6)
NSLog(@"內部建立的訊號block 被執行 createSignal , thread = %@",[NSThread currentThread]);
// 傳送訊號
[subscriber sendNext:@"create Signal for somthing %@"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// 當 [subscriber sendCompleted] 呼叫時就會執行釋放功能的 block (8)
NSLog(@"內部訊號被釋放 disposableWithBlock , thread = %@",[NSThread currentThread]);
}];
}];
}];
// 訂閱最新發出來訊號的 signal (7)
[command.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"執行最近的 signal , x = %@ , thread = %@",x,[NSThread currentThread]);
}];
// executionSignals 這裡傳的 x 值型別為 RACDynamicSignal 型別物件 (5)
[command.executionSignals subscribeNext:^(id _Nullable x) {
NSLog(@"executionSignals subscribeNext x = %@ , thread = %@",x,[NSThread currentThread]);
}];
// 檢視將要執行,每執行完一個步聚 都會呼叫一次檢視哪個 signal block(即 第 x 個 block ) 將被使用 (2)(4)(9)
// signal 的 skip: 方法功能是跳過 skipCount 個 使用 block 的檢視
[[[command executing] skip:0] subscribeNext:^(NSNumber * _Nullable x) {
NSLog(@"executing signal subscribeNext x = %@ , thread = %@",x,[NSThread currentThread]);
}];
// 只執行一次 (1)
[command execute:@"execute"];
// [command execute:@"execute"];
};
}
7、NSObject 分類中 rac_liftSelector… 方法的使用(即等待成所有的 RACSignal 物件傳送完訊號再執行方法) (主程中執行)
/**
7、NSObject 分類中 rac_liftSelector... 方法的使用(即等待成所有的 RACSignal 物件傳送完訊號再執行方法) (主程中執行)
*/
-(void(^)(void))rac_liftSelectorDome
{
return ^{
RACSignal * signalOne = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 現在想發出訊號了
[subscriber sendNext:@"網路請求資料 1"];
// 不需要釋放操作
return nil ;
}];
RACSignal * signalTwo = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 現在想發出訊號了
[subscriber sendNext:@"網路請求資料 2"];
// 不需要釋放操作
return nil ;
}];
[self rac_liftSelector:@selector(updateUIWithSignalOneMessage:signalTwoMessage:) withSignalsFromArray:@[signalOne , signalTwo]];
};
}
// 當據有資料都拿到手後更新UI , 傳的資料就是 signalOne 和 signalTwo 發出來的訊號資料 ,(所以當前設計的接收方法 也必需要有兩個引數,發出的訊號按順序 傳參)
// 假如當前物件方法只設計 傳一個引數,那麼就會導致崩潰
-(void)updateUIWithSignalOneMessage:(id)signalOneMessage signalTwoMessage:(id)signalTwoMessage
{
NSLog(@"signalOneMessage = %@ , signalTwoMessage = %@ , thread = %@",signalOneMessage,signalTwoMessage,[NSThread currentThread]);
}
8、NSNotificationCenter : 使用了 RAC 把監聽通知的方法改成了 block 形勢
/**
8、NSNotificationCenter : 使用了 RAC 把監聽通知的方法改成了 block 形勢
*/
-(void(^)(void))RAC_Notification_Dome
{
return ^{
// 監聽通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidHideNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"NSNotification 1 x = %@",x.userInfo);
}];
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidHideNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"NSNotification 2 x = %@",x.userInfo);
}];
// 發出通知
[[NSNotificationCenter defaultCenter] postNotificationName:UIKeyboardDidHideNotification object:nil];
};
}
9、RAC UITextField 監聽 text 變化 和 繫結 lable.text 永遠等於 textField.text
/**
9、RAC UITextField 監聽 text 變化 和 繫結 lable.text 永遠等於 textField.text
*/
-(void(^)(void))RAC_UITextField_Dome
{
// 解決 block 迴圈引用問題 , 與 @strongify(self); 配套使用
@weakify(self);
return ^{
@strongify(self);
// UITextField RAC使用
UITextField * textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 100, 50)];
textField.backgroundColor = [UIColor redColor];
[self.view addSubview:textField];
[[textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"text = %@ , textField.text = %@ , thread = %@",x,textField.text,[NSThread currentThread]);
}];
// 繫結 lable.text
UILabel * lable = [[UILabel alloc] initWithFrame:CGRectMake(100, 200, 100, 50)];
lable.backgroundColor = [UIColor greenColor];
[self.view addSubview:lable];
// 繫結 lable.text 永遠等於 textField.text
RAC(lable,text) = textField.rac_textSignal ;
};
}
10、RAC KVO 監聽屬性內容變化
/**
10、RAC KVO 監聽屬性內容變化
*/
-(void(^)(void))RAC_KVO_Dome
{
return ^{
[RACObserve(self, age) subscribeNext:^(id _Nullable x) {
NSLog(@"KVO 監聽到 age 內容發生變化 ,變為 %@ , thread = %@",x,[NSThread currentThread]);
}];
};
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.age++ ;
}
11、RACSignal 的 bind 繫結方法
/**
11、RACSignal 的 bind 繫結方法
*/
-(void(^)(void))RACSignalBind
{
return ^{
UITextField * textField = [[UITextField alloc] init];
// bind 裡面的做法:
// (1) 建立一個 RACSignal 物件做為 bind 方法的返值;
// (2) 當我們拿到該返的 RACSignal 類物件 tempSignal 去進行訂閱;
// (3) 然後會執行建立 RACSignal 物件時的 block A ,並在裡面執行 bindBlock 拿到 返回的 block (B返回值為 RACSignal 物件);
// (4) 再執行 block B 就拿到 RACReturnSignal 物件;
// (5) RACReturnSignal 物件 進行訂閱,然後在該訂閱 block 裡面拿到 value 值;
// (6) tempSignal 的 subscriber 訂閱者 傳送訊號值 value , 最後在外面 tempSignal 物件的訂閱就接收到資訊了。
[[textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{
NSLog(@"bind block");
return ^RACSignal * (id _Nullable value, BOOL *stop){
NSLog(@"return block value = %@ can do somthing",value);
return [RACReturnSignal return:value];
};
}] subscribeNext:^(id _Nullable x) {
NSLog(@"signal subscribeNext x = %@",x);
}];
};
}
12、RACReplaySubject 物件的 then: 方法用法
- then 功能:可以使 RACSignal 及其子類的 物件有序接收訊號
/**
12、RACReplaySubject 的 then: 方法用法。
then 功能:可以使 RACSignal 及其子類的 物件有序接收訊號
*/
-(void(^)(void))RACReplaySubjectThenUseDome
{
return ^{
// 在這裡儘量使用 RACReplaySubject 類 ,因為 RACReplaySubject 可以先發送訊號,訂閱程式碼可以放在之後寫。
// 如果 使用 RACSignal 或 RACSubject ,那麼必須要等這些物件訂閱完後,傳送的訊號才能接收的到
RACReplaySubject * subjectA = [RACReplaySubject subject];
// 這就是好處,先發送
[subjectA sendNext:@"AA"];
// 必須要呼叫這個方法才會來到 then 後的 block
[subjectA sendCompleted];
// 按指定的順序接收到訊號
[[[subjectA then:^RACSignal * _Nonnull{
// 當 subjectA 傳送訊號完成後 才執行 當前的 block
RACReplaySubject * subjectB = [RACReplaySubject subject];
// 可以單獨呼叫傳送訊號完成的方法就可以接著執行下一個 then
[subjectB sendCompleted];
return subjectB ;
}] then:^RACSignal * _Nonnull{
// 當 subjectB 傳送訊號完成後 才執行 當前的 block
RACReplaySubject * subjectC = [RACReplaySubject subject];
// subjectC 傳送訊號
[subjectC sendNext:@"CC"];
return subjectC ;
}] subscribeNext:^(id _Nullable x) { // 這個就 "相當於" 訂閱了 subjectC 物件(但真正的物件則不是 subjectC 物件) ,x = @"CC"
NSLog(@"RACReplaySubject C x = %@",x);
}];
};
}
13、合併兩個及以上 RACSignal 或 RACSignal 的子類物件,用新建立的 RACSignal 物件接收多個 RACSignal 或 RACSignal 的子類物件 發出的訊號
- 只要求其中任一的一個被合併物件傳送訊號就能收到
/**
13、合併兩個及以上 RACSignal 或 RACSignal 的子類物件,用新建立的 RACSignal 物件接收多個 RACSignal 或 RACSignal 的子類物件 發出的訊號 (只要求其中任一的一個被合併物件傳送訊號就能收到)
*/
-(void(^)(void))RACSignalMergeDome
{
return ^{
RACReplaySubject * subjectA = [RACReplaySubject subject];
RACReplaySubject * subjectB = [RACReplaySubject subject];
RACReplaySubject * subjectC = [RACReplaySubject subject];
// 三個物件傳送訊號(只需其中一個或多個傳送訊號時,合併的 訊號物件 都可以在訂閱的 block 接收到資訊)
[subjectB sendNext:@"BB"];
[subjectA sendNext:@"AA"];
[subjectC sendNext:@"CC"];
// 合併兩個訊號物件變成一個接收訊號物件 subjectD , subjectD 訂閱 接收 subjectB 和 subjectA 傳送的訊號
[[[subjectA merge:subjectB] merge:subjectC] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
};
}
14、壓縮兩個及以上 RACSignal 或 RACSignal 的子類物件,用新建立的 RACSignal 物件同時接收多個 RACSignal 或 RACSignal 的子類物件 發出的訊號
- 必須所有 的被壓縮物件 一起傳送訊號 才能收到
- 注意:解析時需要一層一層的解析
/**
14、壓縮兩個及以上 RACSignal 或 RACSignal 的子類物件,用新建立的 RACSignal 物件同時接收多個 RACSignal 或 RACSignal 的子類物件 發出的訊號 (必須所有 的被壓縮物件 一起傳送訊號 才能收到)(注意:解析時需要一層一層的解析)
*/
-(void(^)(void))RACSignalZipWithDome
{
return ^{
RACReplaySubject * subjectA = [RACReplaySubject subject];
RACReplaySubject * subjectB = [RACReplaySubject subject];
RACReplaySubject * subjectC = [RACReplaySubject subject];
// 三個物件同時傳送訊號,缺一不可
[subjectA sendNext:@"AA"];
[subjectB sendNext:@"BB"];
[subjectC sendNext:@"CC"];
// 合併兩個訊號物件變成一個接收訊號物件 subjectD , subjectD 訂閱 接收 subjectB 和 subjectA 傳送的訊號
// x 型別為 元組 RACTwoTuple 型別:解析使用
[[[subjectA zipWith:subjectB] zipWith:subjectC] subscribeNext:^(id _Nullable x) {
// 注意:元組需要 一層一層 地解析
RACTupleUnpack(RACTuple * AB , NSString * C) = x ;
RACTupleUnpack(NSString * A , NSString * B) = AB ;
NSLog(@"A = %@ , B = %@ , C = %@",A , B , C);
}];
};
}
15、合併兩個及以上 RACSignal 或 RACSignal 的子類物件,用新建立的 RACSignal 物件 同時接收多個 RACSignal 或 RACSignal 的子類物件 發出的訊號
- 任意一個 被合併的物件 傳送的訊號 都能收到
- 注意:解析時需要一層一層的解析
/**
15、合併兩個及以上 RACSignal 或 RACSignal 的子類物件,用新建立的 RACSignal 物件 同時接收多個 RACSignal 或 RACSignal 的子類物件 發出的訊號 (任意一個 被合併的物件 傳送的訊號 都能收到)(注意:解析時需要一層一層的解析)
*/
-(void(^)(void))RACSignalCombineLatestWithDome
{
return ^{
RACReplaySubject * subjectA = [RACReplaySubject subject];
RACReplaySubject * subjectB = [RACReplaySubject subject];
RACReplaySubject * subjectC = [RACReplaySubject subject];
// 三個物件同時傳送訊號,缺一不可
[subjectA sendNext:@"AA"];
[subjectB sendNext:@"BB"];
[subjectC sendNext:@"CC"];
// 1.合併三個訊號物件變成一個接收訊號物件 subjectD , subjectD 訂閱 接收 subjectB 和 subjectA 傳送的訊號
// x 型別為 元組 RACTwoTuple 型別:解析使用
[[[subjectA combineLatestWith:subjectB] combineLatestWith:subjectC] subscribeNext:^(id _Nullable x) {
// 注意:元組需要 一層一層 地解析
RACTupleUnpack(RACTuple * AB , NSString * C) = x ;
RACTupleUnpack(NSString * A , NSString * B) = AB ;
NSLog(@"A = %@ , B = %@ , C = %@",A , B , C);
}];
// 2.也可以把那些訊號傳的引數聚合成一個值
// 遵守 NSFastEnumeration 協議的類都可成為陣列
// reduce block 引數可以自己根據訊號設定
[[RACSignal combineLatest:@[subjectB,subjectA,subjectC] reduce:^id (NSString * signalA,NSString * signalB,NSString * signalC){
// 把這 三個中任意 一個發出的訊號值 聚合成一個值 NSString 型別
return [NSString stringWithFormat:@"A = %@ , B = %@ , C = %@",signalA , signalB , signalC];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"聚合後三個值變成一個 NSString 型別的值: %@",x);
}];
// 3.也可以用聚合繫結做法
UILabel * lable = [[UILabel alloc] init];
RAC(lable , text) = [RACSignal combineLatest:@[subjectB,subjectA,subjectC] reduce:^id (NSString * signalA,NSString * signalB,NSString * signalC){
// 把這 三個中任意 一個發出的訊號值 聚合成一個值 NSString 型別
return [NSString stringWithFormat:@"A = %@ , B = %@ , C = %@",signalA , signalB , signalC];
}];
NSLog(@"lable.text = %@",lable.text);
};
}
16、RACSignal 的 map 攔截訊號發出的訊號和處理資料
/**
16、RACSignal 的 map 攔截訊號發出的訊號和處理資料
*/
-(void(^)(void))RACSignalMapDome
{
return ^{
RACReplaySubject * signal = [RACReplaySubject subject];
[[signal map:^id _Nullable(id _Nullable value) {
return [NSString stringWithFormat:@"%@ (攔截髮出的訊號,拼接個想要的東西)",value];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"接收到處理後的資訊 = %@",x);
}];
[signal sendNext:@"@(當前訊號的資訊)"];
};
}
17、訊號中的訊號,RACSignal 的 flattenMap 物件方法,用來接收訊號物件value 和 訊號物件value發出的資訊
/**
17、訊號中的訊號,RACSignal 的 flattenMap 物件方法,用來接收訊號物件value 和 訊號物件value發出的資訊
*/
-(void(^)(void))RACSignalFlattenMapDome
{
return ^{
RACReplaySubject * signal = [RACReplaySubject subject];
RACSubject * subject = [RACSubject subject];
[[signal flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
// value 是訊號物件 == subject
return [value map:^id _Nullable(id _Nullable value) {
return [NSString stringWithFormat:@"(新增攔截訊號處理訊號) (%@)",value];
}];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"接收到處理後的資訊 = %@",x);
}];
[signal sendNext:subject];
[subject sendNext:@" subject 發出訊號了"];
};
}
18、訊號過濾器:RACSignal 的 filter: 方法,用來設定一個條件發出的訊號才會被接收到
/**
18、訊號過濾器:RACSignal 的 filter: 方法,用來設定一個條件發出的訊號才會被接收到
*/
-(void(^)(void))RACSignalFilterDome
{
return ^{
RACReplaySubject * replaySubject = [RACReplaySubject replaySubjectWithCapacity:1];
// filter block 是一個過濾器,只有滿足條件發出的訊號才會被接收到
[[replaySubject filter:^BOOL(id _Nullable value) {
return ((NSString *)value).length >= 6 ;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"接收到訊號 = %@",x);
}];
// // 發出的訊號長度為 5 時,訂閱收不到訊號資訊
// [replaySubject sendNext:@"12345"];
// 發出的訊號長度為 >= 6 時,訂閱收到訊號了資訊
[replaySubject sendNext:@"123456"];
};
}
19、RACSignal 訊號物件 與 定時器的關係
/**
19、RACSignal 訊號物件 與 定時器的關係
*/
-(void(^)(void))RACSignalAndTimerDome
{
return ^{
// 1、定時器
// TimeInterval : 間隔時間,秒
// repeats : 是否重複
// blokc : 呼叫程式碼塊 (在主執行緒中執行)
[NSTimer scheduledTimerWithTimeInterval:1 repeats:NO block:^(NSTimer * _Nonnull timer) {
NSLog(@"每隔一秒呼叫一次當前 block , thread = %@",[NSThread currentThread]);
}];
// 2、RACSignal 制定定時器
// interval : 間隔的時間,秒
/**
onScheduler : 多執行緒 , 佇列
mainThreadScheduler : 主執行緒中 執行訂閱程式碼塊
currentScheduler : 在當前建立時的執行緒中 執行訂閱程式碼塊
*/
/**
schedulerWithPriority: 或 schedulerWithPriority:name: 優先順序 , name 表示執行緒名
// 優先順序高,開起 新的執行緒
RACSchedulerPriorityHigh = DISPATCH_QUEUE_PRIORITY_HIGH,
// 預設優先順序,開起 新的執行緒
RACSchedulerPriorityDefault = DISPATCH_QUEUE_PRIORITY_DEFAULT,
// 優先順序低,開起 新的執行緒
RACSchedulerPriorityLow = DISPATCH_QUEUE_PRIORITY_LOW,
// app 進入後臺也可以呼叫,開起 新的執行緒
RACSchedulerPriorityBackground = DISPATCH_QUEUE_PRIORITY_BACKGROUND,
*/
[[RACReplaySubject interval:1 onScheduler:[RACScheduler schedulerWithPriority:RACSchedulerPriorityLow]] subscribeNext:^(NSDate * _Nullable x) {
// x 是當前的時間
NSLog(@"每隔一秒呼叫訂閱程式碼:x = %@ , 線上程 thread = %@",x,[NSThread currentThread]);
}];
// 3、使用 RACSignal 訊號 延時
[[[RACReplaySubject createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"2秒後呼叫訂閱 block"];
return nil ;
}] delay:5] // 延時 5秒 再
subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
};
}