iOS ReactiveObjC使用

image

RAC 指的就是 RactiveCocoa ,是 Github 的一個(gè)開源框架,能夠幫我們提供大量方便的事件處理方案,讓我們更簡(jiǎn)單粗暴地去處理事件,現(xiàn)在分為 ReactiveObjCReactiveSwift ,兩個(gè)框架的功能使用相似,由于正好在學(xué)習(xí)這個(gè)然后公司項(xiàng)目是用 OC 寫的,所以將 ReactiveObjC 的使用方法記錄一下。

下載地址:https://github.com/ReactiveCocoa/ReactiveObjC

ReactiveObjC常用使用

  • 1、RACSignal 信號(hào)
  • 2、RACSubject 信號(hào),和代理的用法類似,通常用來代替代理
  • 3、RACTuple 元祖
  • 4、便利 Array 數(shù)組和 Dictionary 字典,可以省去使用 for 循環(huán)來遍歷
  • 5、監(jiān)聽 TextField 的輸入改變
  • 6、監(jiān)聽 Button 點(diǎn)擊事件
  • 7、按鈕狀態(tài)實(shí)時(shí)監(jiān)聽
  • 8、監(jiān)聽 Notification 通知事件
  • 9、代替 Delegate 代理方法
  • 10、代替 KVO 監(jiān)聽
  • 11、代替 NSTimer 計(jì)時(shí)器
  • 12、處理一個(gè)界面,多個(gè)請(qǐng)求問題

ReactiveObjC 的使用

#import <ReactiveObjC/ReactiveObjC.h>

RAC 的核心思想:創(chuàng)建信號(hào) - 訂閱信號(hào) - 發(fā)送信號(hào) ,并且在 RAC 中我們會(huì)看到大量的 block ,所以在使用之前可以再重新溫習(xí)一下 block 的使用。

1. RACSignal 信號(hào)

/* 創(chuàng)建信號(hào) */
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {

    /* 發(fā)送信號(hào) */
    [subscriber sendNext:@"發(fā)送信號(hào)"];

    return nil;
}];

/* 訂閱信號(hào) */
RACDisposable *disposable = [signal subscribeNext:^(id  _Nullable x) {

    NSLog(@"信號(hào)內(nèi)容:%@", x);
}];

/* 取消訂閱 */
[disposable dispose];

2. RACSubject 信號(hào)

和代理的用法類似,通常用來代替代理,有了它,就不必要定義代理了。

/* 創(chuàng)建信號(hào) */
RACSubject *subject = [RACSubject subject];

/* 發(fā)送信號(hào) */
[subject sendNext:@"發(fā)送信號(hào)"];

/* 訂閱信號(hào)(通常在別的視圖控制器中訂閱,與代理的用法類似) */
[subject subscribeNext:^(id  _Nullable x) {

    NSLog(@"信號(hào)內(nèi)容:%@", x);
}];

3. RACTuple 元祖

RAC 的元祖,跟我們 OC 的數(shù)組其實(shí)是一樣的,它其實(shí)就是封裝了我們 OC 的數(shù)組。

/* 創(chuàng)建元祖 */
RACTuple *tuple = [RACTuple tupleWithObjects:@"1", @"2", @"3", @"4", @"5", nil];

/* 從別的數(shù)組中獲取內(nèi)容 */
RACTuple *tuple = [RACTuple tupleWithObjectsFromArray:@[@"1", @"2", @"3", @"4", @"5"]];

/* 利用 RAC 宏快速封裝 */
RACTuple *tuple = RACTuplePack(@"1", @"2", @"3", @"4", @"5");

NSLog(@"取元祖內(nèi)容:%@", tuple[0]);
NSLog(@"第一個(gè)元素:%@", [tuple first]);
NSLog(@"最后一個(gè)元素:%@", [tuple last]);

4. 便利 Array 數(shù)組和 Dictionary 字典

可以省去使用 for 循環(huán)來遍歷。

/* 遍歷數(shù)組 */
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
[array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {

    NSLog(@"數(shù)組內(nèi)容:%@", x); // x 可以是任何對(duì)象
}];

/* 遍歷字典 */
NSDictionary *dictionary = @{@"key1":@"value1", @"key2":@"value2", @"key3":@"value3"};
[dictionary.rac_sequence.signal subscribeNext:^(RACTuple * _Nullable x) {

    RACTupleUnpack(NSString *key, NSString *value) = x; // x 是一個(gè)元祖,這個(gè)宏能夠?qū)?key 和 value 拆開
    NSLog(@"字典內(nèi)容:%@:%@", key, value);
}];

下面兩個(gè)方法都是將數(shù)組內(nèi)容全部換為 0 ,第一個(gè)是單個(gè)操作,,第二個(gè)是一次性全部替換,兩個(gè)方法都不會(huì)改變?cè)瓟?shù)組內(nèi)容,操作完后都會(huì)生成一個(gè)新的數(shù)組,省去了創(chuàng)建可變數(shù)組然后遍歷出來單個(gè)添加的步驟。

/* 內(nèi)容操作 */
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
NSArray *newArray = [[array.rac_sequence map:^id _Nullable(id  _Nullable value) {

    NSLog(@"數(shù)組內(nèi)容:%@", value);

    return @"0"; // 將所有內(nèi)容替換為 0

}] array];

/* 內(nèi)容快速替換 */
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
NSArray *newArray = [[array.rac_sequence mapReplace:@"0"] array]; // 將所有內(nèi)容替換為 0

5. 監(jiān)聽 TextField 的輸入改變

可以省去設(shè)置 delegate 和實(shí)現(xiàn)代理方法的步驟。

/* 監(jiān)聽 TextField 的輸入(內(nèi)容改變就會(huì)調(diào)用) */
[[textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {

    NSLog(@"輸入框內(nèi)容:%@", x);
}];

/* 添加監(jiān)聽條件 */
[[textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {

    return value.length > 5; // 表示輸入文字長(zhǎng)度 > 5 時(shí)才會(huì)調(diào)用下面的 block

}] subscribeNext:^(NSString * _Nullable x) {

     NSLog(@"輸入框內(nèi)容:%@", x);
}];

6. 監(jiān)聽 Button 點(diǎn)擊事件

可以省去 addTarget 添加事件和創(chuàng)建方法的步驟。

[[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {

    NSLog(@"%@ 按鈕被點(diǎn)擊了", x); // x 是 button 按鈕對(duì)象
}];

7. 登錄按鈕狀態(tài)實(shí)時(shí)監(jiān)聽

下面表示只有 用戶名密碼 輸入框內(nèi)容都大于 0 時(shí),登錄 按鈕才可以點(diǎn)擊,而且狀態(tài)是實(shí)時(shí)監(jiān)聽的,一句代碼就能完成這個(gè)功能。

RAC(_loginButton, enabled) = [RACSignal combineLatest:@[_username.rac_textSignal, _password.rac_textSignal] reduce:^id _Nullable(NSString * username, NSString * password){

    return @(username.length && password.length);
}];

8. 監(jiān)聽 Notification 通知事件

可省去在 -(void)dealloc {} 中清除通知和監(jiān)聽通知?jiǎng)?chuàng)建方法的步驟。

[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {

    NSLog(@"%@ 鍵盤彈起", x); // x 是通知對(duì)象
}];

9. 代替 Delegate 代理方法

可以省去監(jiān)聽以及設(shè)置 delegate 的步驟,下面表示只要 view 中執(zhí)行了 btnClick 這個(gè)方法,就會(huì)發(fā)送信號(hào)執(zhí)行這個(gè)回調(diào)。

[[view rac_signalForSelector:@selector(btnClick)] subscribeNext:^(RACTuple * _Nullable x) {

    NSLog(@" view 中的按鈕被點(diǎn)擊了");
}];

10. 代替 KVO 監(jiān)聽

可以代替 KVO 監(jiān)聽,下面表示把監(jiān)聽 viewframe 屬性改變轉(zhuǎn)換成信號(hào),只要值改變就會(huì)發(fā)送信號(hào)。

[[view rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id  _Nullable x) {

    NSLog(@"屬性的改變:%@", x); // x 是監(jiān)聽屬性的改變結(jié)果
}];

還有一種更簡(jiǎn)單的寫法,就是利用 RAC 的宏,和上面的效果是一樣的。

[RACObserve(view, frame) subscribeNext:^(id  _Nullable x) {

    NSLog(@"屬性的改變:%@", x); // x 是監(jiān)聽屬性的改變結(jié)果
}];

11. 代替 NSTimer 計(jì)時(shí)器

可以代替 NSTimer 使用。

@interface ViewController ()

@property (nonatomic, strong) RACDisposable *disposable;

@end

/* 定義計(jì)時(shí)器監(jiān)聽 */
self.disposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {

    NSLog(@"當(dāng)前時(shí)間:%@", x); // x 是當(dāng)前的系統(tǒng)時(shí)間

    /* 關(guān)閉計(jì)時(shí)器 */
    [_disposable dispose];
}];

12. 處理一個(gè)界面,多個(gè)請(qǐng)求問題

#pragma mark - 處理一個(gè)界面,多個(gè)請(qǐng)求問題
- (void)testRACSignals {
    
    RACSignal *hotSignal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        // Request hotData
        [subscriber sendNext:@"hotData"];
        return nil;
    }];
    RACSignal *newSignal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        // Request newData
        [subscriber sendNext:@"newData"];
        return nil;
    }];
    
    // @selector當(dāng)數(shù)組所有信號(hào)都發(fā)送sendNext
    // 有幾個(gè)信號(hào)就必須有幾個(gè)參數(shù),參數(shù)就是信號(hào)發(fā)出值
    [self rac_liftSelector:@selector(updateUIWithHotData:newData:) withSignalsFromArray:@[hotSignal, newSignal]];
}
// 當(dāng)所有信號(hào)都發(fā)送sendNext,執(zhí)行。
- (void)updateUIWithHotData:(id)hotData newData:(id)newData {
    NSLog(@"hotData = %@  newData = %@", hotData, newData);
}


持續(xù)更新,學(xué)習(xí)到新的知識(shí)在記錄下來,有需要的可以收藏一下。

將來的你,一定會(huì)感激現(xiàn)在拼命的自己,愿自己與讀者的開發(fā)之路無限美好。

我的傳送門: 博客簡(jiǎn)書 、微博 、GitHub 。

鏈接:http://www.itdecent.cn/p/0845b1a07bfa
http://www.itdecent.cn/p/d7e254473b9e

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容