iOS RAC - 基本用法

文章系列
《RACSignal 》
《RACDisposable》
《RACSubject倒淫、RACReplaySubject》
《iOS RAC - 基本用法》
《iOS RAC - 定時器》
《iOS RAC - RACMulticastConnection》
《iOS RAC - RACCommand》
《iOS RAC - 核心方法bind》
《iOS RAC - 集合RACTuple正歼、RACSequence》
《iOS RAC - rac_leftSelector》
《iOS RAC - 映射》
《iOS RAC - 過濾》
《iOS RAC - 登錄頁面,MVVM》

1吩翻、監(jiān)聽方法,并且可以通過元組把參數(shù)傳出

  • 第一步:創(chuàng)建一個工程,在Main.stroyboard中添加一個View萄涯,并且在view 中添加一個button晒奕,然后實(shí)現(xiàn)button的點(diǎn)擊方法闻书。
1
  • 第二步:拖入屬性到ViewController中
2

然后如果我們要想在ViewController中處理到按鈕的點(diǎn)擊事件,我門常用的方式有:代理脑慧、block或者通知等等魄眉,上面的方法可以做到,但是對比起來RAC代碼就“太多了”漾橙,而且不太方便杆融。
OK,使用RAC如何監(jiān)聽呢霜运?

    [[self.redView rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(RACTuple * _Nullable x) {
        //        NSLog(@"你竟然響應(yīng)我了 厲害了");
        NSLog(@"%@",x);
    }];
這里先別管代碼啥意思脾歇,首先是不是異常簡短蒋腮,并且內(nèi)聚。

<br />
當(dāng)然了我們還是要點(diǎn)進(jìn)去看看的:點(diǎn)擊方法名字藕各,進(jìn)入內(nèi)部查看實(shí)現(xiàn)

- (RACSignal *)rac_signalForSelector:(SEL)selector {
    NSCParameterAssert(selector != NULL);

    return NSObjectRACSignalForSelector(self, selector, NULL);
}

發(fā)現(xiàn)進(jìn)來了還有一層池摧,在點(diǎn)擊進(jìn)去

  • 從上面可以看出返回值是信號,既然是信號那就可以訂閱
  • 內(nèi)部創(chuàng)建的是subject激况,那就可以發(fā)送信號作彤,訂閱信號
    所以我么在調(diào)用rac_signalForSelector這個方法可以直接訂閱,內(nèi)部又是一個subject乌逐,所以他會發(fā)送信號給到我們

<br />
2竭讳、KVO

通常我們要使用KVO需要addObserver并且還要在observeValueForKeyPath...這個方法中去監(jiān)聽,
如果一個界面監(jiān)聽多個還需要判斷浙踢,還必須記得釋放掉绢慢。
但是這些東西在RAC中就做了一層包裝,現(xiàn)在我們?nèi)绻氡O(jiān)聽對象的某個屬性洛波,就可以寫如下代碼就可以完成胰舆,
并且針對某個屬性都會產(chǎn)生不同的信號,我們只需要監(jiān)聽所產(chǎn)生的信號在進(jìn)行處理就可以了

- (void)repleacKVO{
   [_redView rac_observeKeyPath:@"frame" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
       NSLog(@"1 - %@",value);
   }];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
   _redView.frame = CGRectMake(50, 60, 200, 200);
}

上面的代碼就可以完成去監(jiān)聽蹬挤,但是你有沒有感覺是一般的寫法極其類似啊缚窿,當(dāng)然了,我們還有跟簡單的寫法的

寫法二:

//方法2
    [[_redView rac_valuesForKeyPath:@"frame" observer:nil] subscribeNext:^(id  _Nullable x) {
        NSLog(@"2 - %@",x);
    }];

當(dāng)你認(rèn)為寫法二已經(jīng)足夠簡單的時候我不會告訴你還有寫法三

寫法三:

//方法三
    [RACObserve(_redView, frame) subscribeNext:^(id  _Nullable x) {
        NSLog(@"3 - %@",x);
    }];

但是這里有一件事情要注意:寫法二焰扳、寫法三需要在程序運(yùn)行的時候就會監(jiān)聽到倦零,通過log就可以看出區(qū)別。

可以看到蓝翰,我運(yùn)行程序?qū)懛ǘ馊啤⑷痛蛴×藬?shù)據(jù),但是寫法一是等到改變值了在打印的數(shù)據(jù)畜份。

<br />
3诞帐、監(jiān)聽事件
假設(shè)一種情況,我們在storyboard中有一個button爆雹,這個時候我們要監(jiān)聽按鈕的點(diǎn)擊事件停蕉,通常情況下我們是直接脫線到viewcontroller中,然后做處理。但是在RAC中我們就可以這樣做钙态。

  • 創(chuàng)建一個button慧起,并且拖入到viewcontroller中,命名為btn
引用button
  • 監(jiān)聽按鈕點(diǎn)擊事件
- (void)listenEvent{
    [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        NSLog(@"%@",x);
    }];
}

一起去看看內(nèi)部實(shí)現(xiàn)吧

- (RACSignal *)rac_signalForControlEvents:(UIControlEvents)controlEvents {
    @weakify(self);

    return [[RACSignal
        createSignal:^(id<RACSubscriber> subscriber) {
            @strongify(self);

            [self addTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents];

            RACDisposable *disposable = [RACDisposable disposableWithBlock:^{
                [subscriber sendCompleted];
            }];
            [self.rac_deallocDisposable addDisposable:disposable];

            return [RACDisposable disposableWithBlock:^{
                @strongify(self);
                [self.rac_deallocDisposable removeDisposable:disposable];
                [self removeTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents];
            }];
        }]
        setNameWithFormat:@"%@ -rac_signalForControlEvents: %lx", RACDescription(self), (unsigned long)controlEvents];
}

里面最關(guān)鍵的代碼就是[self addTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents];
self 就是btn本身册倒,因?yàn)槭?code>btn調(diào)用的方法
然后targetsubscriber(訂閱者)
方法是 :sendNext:
事件是傳入的事件蚓挤,
所以現(xiàn)在按鈕的點(diǎn)擊方法會通過subscriber去調(diào)用sendNext方法,我們之前有提到過,RACSignal,所以這個時候我們訂閱他就可以拿到sendNext的值灿意。

事件

<br />
4估灿、通知
之前我們寫通知是這樣子的

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noti:) name:@"noti" object:nil];

這樣子做沒什么不對,唯一有一點(diǎn)就是小麻煩了一點(diǎn)了需要自己實(shí)現(xiàn)一個方法去做處理缤剧,但是這點(diǎn)在RAC中就截然不同了馅袁。

[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"%@",x);
    }];

這樣子幫助我們處理事件是不是非常的內(nèi)聚呢?并且管理起來也很方便荒辕。但是內(nèi)部是怎么樣處理的呢汗销?
一起來揭開他的面紗

- (RACSignal *)rac_addObserverForName:(NSString *)notificationName object:(id)object {
    @unsafeify(object);
    return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
        @strongify(object);
        id observer = [self addObserverForName:notificationName object:object queue:nil usingBlock:^(NSNotification *note) {
            [subscriber sendNext:note];
        }];

        return [RACDisposable disposableWithBlock:^{
            [self removeObserver:observer];
        }];
    }] setNameWithFormat:@"-rac_addObserverForName: %@ object: <%@: %p>", notificationName, [object class], object];
}

沒錯又是RACSignal,這個里面的代碼很簡單抵窒,就是調(diào)用系統(tǒng)提供的方法弛针,在block中使用訂閱者發(fā)布信息,在RACDisposable中把observer移除估脆。

<br />
5钦奋、監(jiān)聽textfield舒輸入
首先我們先在storyboard中拖入控件UITextfield,然后拖入到ViewController

textfied

在常規(guī)做法中我們需要addtarget或者直接在storyboard中把對應(yīng)的事件拖入到ViewController中疙赠,但是RAC里面你只需要

    [_textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@",x);
    }];

驚喜不驚喜,意外不意外朦拖?對的就是那么簡單圃阳。
現(xiàn)在我們就實(shí)時拿到textfield輸入到值,這個時候假設(shè)一個需求璧帝,要把textfield的值顯示在一個label上捍岳,怎么做呢?很簡單睬隶,我們只需要這樣子

- (void)listenTextfiledInput{
    [_textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@",x);
        _label.text = x;
    }];
}

效果圖如下


但是其實(shí)還有一種更簡單的寫法:

RAC(_label,text) = _textField.rac_textSignal;

其中RAC是一個宏锣夹,宏的用法:

  • RAC(對象,對象的屬性) = (一個信號);
    比如:RAC(btn,enable) = (RACSignal) 按鈕的enable等于一個信號

<br />
6苏潜、代替代理
代理作為項(xiàng)目總頻繁使用到一個寫法機(jī)制银萍,我們通常需要定義代理,實(shí)現(xiàn)代理協(xié)議方法恤左,并且還要注意循環(huán)引用等問題存在贴唇,RAC也可以做到代替代理。

想必看到上面那張圖大家就應(yīng)該知道如何搭建UI了飞袋,創(chuàng)建一個view戳气,內(nèi)部添加一個button
我們要做的就是監(jiān)聽button按下事件巧鸭。

1瓶您、在處理完成UI之后,創(chuàng)建一個GreenView,并導(dǎo)入頭文件#import "ReactiveObjC.h"

2呀袱、創(chuàng)建一個RACSubject并且命名為btnClickSignal芯肤,這里大家需要注意是命名盡量規(guī)范,否則以后維護(hù)起來你會很痛苦压鉴。然后這里為什么會用RACSubject崖咨,因?yàn)?code>RACSubject可以自己控制發(fā)送數(shù)據(jù)時間。

目前為止代碼應(yīng)該類似于這樣子:

#import <UIKit/UIKit.h>
#import "ReactiveObjC.h"
@interface GreenView : UIView
@property (nonatomic,strong) RACSubject *btnClickSignal;
@end

3油吭、進(jìn)入.m文件击蹲,完成下面代碼

#import "GreenView.h"

@implementation GreenView

- (RACSubject *)btnClickSignal{
    if (!_btnClickSignal) {
        _btnClickSignal = [RACSubject subject];
    }
    return _btnClickSignal;
}

- (IBAction)btnClick:(id)sender{
    [_btnClickSignal sendNext:@"我可以代替代理哦"];
}

@end

上面代碼中完成了兩個功能:懶加載RACSubject,以及在按鈕點(diǎn)擊時候發(fā)布數(shù)據(jù)

然后回到ViewController

- (void)replaceDelegate{
    [_greenView.btnClickSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
}

效果圖


是不是比傳統(tǒng)的代理來的更簡單婉宰、內(nèi)聚呢歌豺?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市心包,隨后出現(xiàn)的幾起案子类咧,更是在濱河造成了極大的恐慌,老刑警劉巖蟹腾,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痕惋,死亡現(xiàn)場離奇詭異,居然都是意外死亡娃殖,警方通過查閱死者的電腦和手機(jī)值戳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炉爆,“玉大人堕虹,你說我怎么就攤上這事》沂祝” “怎么了赴捞?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長郁稍。 經(jīng)常有香客問我赦政,道長,這世上最難降的妖魔是什么艺晴? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任昼钻,我火速辦了婚禮,結(jié)果婚禮上封寞,老公的妹妹穿的比我還像新娘然评。我一直安慰自己,他們只是感情好狈究,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布碗淌。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亿眠。 梳的紋絲不亂的頭發(fā)上碎罚,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音纳像,去河邊找鬼荆烈。 笑死,一個胖子當(dāng)著我的面吹牛竟趾,可吹牛的內(nèi)容都是我干的憔购。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼岔帽,長吁一口氣:“原來是場噩夢啊……” “哼玫鸟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起犀勒,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤屎飘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贾费,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钦购,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年铸本,在試婚紗的時候發(fā)現(xiàn)自己被綠了肮雨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡箱玷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出陌宿,到底是詐尸還是另有隱情锡足,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布壳坪,位于F島的核電站舶得,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏爽蝴。R本人自食惡果不足惜沐批,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝎亚。 院中可真熱鬧九孩,春花似錦、人聲如沸发框。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宪拥,卻和暖如春仿野,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背她君。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工脚作, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缔刹。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓球涛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親桨螺。 傳聞我的和親對象是個殘疾皇子宾符,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容