《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、監聽方法,並且可以通過元組把參數傳出
- 第一步:創建一個工程,在Main.stroyboard中添加一個View,並且在view 中添加一個button,然后實現button的點擊方法。

- 第二步:拖入屬性到ViewController中

然后如果我們要想在ViewController中處理到按鈕的點擊事件,我門常用的方式有:代理、block或者通知等等,上面的方法可以做到,但是對比起來RAC代碼就“太多了”,而且不太方便。
OK,使用RAC如何監聽呢?
[[self.redView rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(RACTuple * _Nullable x) { // NSLog(@"你竟然響應我了 厲害了"); NSLog(@"%@",x); }]; 這里先別管代碼啥意思,首先是不是異常簡短,並且內聚。
<br />
當然了我們還是要點進去看看的:點擊方法名字,進入內部查看實現
- (RACSignal *)rac_signalForSelector:(SEL)selector { NSCParameterAssert(selector != NULL); return NSObjectRACSignalForSelector(self, selector, NULL); }
發現進來了還有一層,在點擊進去

- 從上面可以看出返回值是信號,既然是信號那就可以訂閱
- 內部創建的是subject,那就可以發送信號,訂閱信號
所以我么在調用rac_signalForSelector
這個方法可以直接訂閱,內部又是一個subject
,所以他會發送信號給到我們
<br />
2、KVO
通常我們要使用KVO需要addObserver
並且還要在observeValueForKeyPath...
這個方法中去監聽,
如果一個界面監聽多個還需要判斷,還必須記得釋放掉。
但是這些東西在RAC中就做了一層包裝,現在我們如果想監聽對象的某個屬性,就可以寫如下代碼就可以完成,
並且針對某個屬性都會產生不同的信號,我們只需要監聽所產生的信號在進行處理就可以了
- (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); }
上面的代碼就可以完成去監聽,但是你有沒有感覺是一般的寫法極其類似啊,當然了,我們還有跟簡單的寫法的
寫法二:
//方法2 [[_redView rac_valuesForKeyPath:@"frame" observer:nil] subscribeNext:^(id _Nullable x) { NSLog(@"2 - %@",x); }];
當你認為寫法二已經足夠簡單的時候我不會告訴你還有寫法三
寫法三:
//方法三 [RACObserve(_redView, frame) subscribeNext:^(id _Nullable x) { NSLog(@"3 - %@",x); }];
但是這里有一件事情要注意:寫法二、寫法三需要在程序運行的時候就會監聽到,通過log就可以看出區別。

可以看到,我運行程序寫法二、三就打印了數據,但是寫法一是等到改變值了在打印的數據。
<br />
3、監聽事件
假設一種情況,我們在storyboard
中有一個button
,這個時候我們要監聽按鈕的點擊事件,通常情況下我們是直接脫線到viewcontroller
中,然后做處理。但是在RAC中我們就可以這樣做。
- 創建一個
button
,並且拖入到viewcontroller
中,命名為btn

- 監聽按鈕點擊事件
- (void)listenEvent{ [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) { NSLog(@"%@",x); }]; }
一起去看看內部實現吧
- (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]; }
里面最關鍵的代碼就是[self addTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents];
self
就是btn
本身,因為是btn
調用的方法
然后target
是subscriber(訂閱者)
方法是 :sendNext:
事件是傳入的事件,
所以現在按鈕的點擊方法會通過subscriber
去調用sendNext方法
,我們之前有提到過,RACSignal
,所以這個時候我們訂閱他就可以拿到sendNext
的值。

<br />
4、通知
之前我們寫通知是這樣子的
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noti:) name:@"noti" object:nil];
這樣子做沒什么不對,唯一有一點就是小麻煩了一點了需要自己實現一個方法去做處理,但是這點在RAC中就截然不同了。
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) { NSLog(@"%@",x); }];
這樣子幫助我們處理事件是不是非常的內聚呢?並且管理起來也很方便。但是內部是怎么樣處理的呢?
一起來揭開他的面紗
- (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
,這個里面的代碼很簡單,就是調用系統提供的方法,在block
中使用訂閱者發布信息,在RACDisposable
中把observer
移除。
<br />
5、監聽textfield
舒輸入
首先我們先在storyboard中
拖入控件UITextfield
,然后拖入到ViewController

在常規做法中我們需要addtarget
或者直接在storyboard
中把對應的事件拖入到ViewController
中,但是RAC里面你只需要
[_textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) { NSLog(@"%@",x); }];
驚喜不驚喜,意外不意外?對的就是那么簡單。
現在我們就實時拿到textfield
輸入到值,這個時候假設一個需求,要把textfield
的值顯示在一個label
上,怎么做呢?很簡單,我們只需要這樣子
- (void)listenTextfiledInput{ [_textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) { NSLog(@"%@",x); _label.text = x; }]; }
效果圖如下

但是其實還有一種更簡單的寫法:
RAC(_label,text) = _textField.rac_textSignal;
其中RAC是一個宏,宏的用法:
- RAC(對象,對象的屬性) = (一個信號);
比如:RAC(btn,enable) = (RACSignal) 按鈕的enable等於一個信號
<br />
6、代替代理
代理作為項目總頻繁使用到一個寫法機制,我們通常需要定義代理,實現代理協議方法,並且還要注意循環引用等問題存在,RAC也可以做到代替代理。
想必看到上面那張圖大家就應該知道如何搭建UI了,創建一個view
,內部添加一個button
。
我們要做的就是監聽button
按下事件。
1、在處理完成UI之后,創建一個GreenView
,並導入頭文件#import "ReactiveObjC.h"
2、創建一個RACSubject
並且命名為btnClickSignal
,這里大家需要注意是命名盡量規范,否則以后維護起來你會很痛苦。然后這里為什么會用RACSubject
,因為RACSubject
可以自己控制發送數據時間。
目前為止代碼應該類似於這樣子:
#import <UIKit/UIKit.h> #import "ReactiveObjC.h" @interface GreenView : UIView @property (nonatomic,strong) RACSubject *btnClickSignal; @end
3、進入.m
文件,完成下面代碼
#import "GreenView.h" @implementation GreenView - (RACSubject *)btnClickSignal{ if (!_btnClickSignal) { _btnClickSignal = [RACSubject subject]; } return _btnClickSignal; } - (IBAction)btnClick:(id)sender{ [_btnClickSignal sendNext:@"我可以代替代理哦"]; } @end
上面代碼中完成了兩個功能:懶加載RACSubject
,以及在按鈕點擊時候發布數據
然后回到ViewController
中
- (void)replaceDelegate{ [_greenView.btnClickSignal subscribeNext:^(id _Nullable x) { NSLog(@"%@",x); }]; }
效果圖

是不是比傳統的代理來的更簡單、內聚呢?
作者:Codepgq
鏈接:https://www.jianshu.com/p/cd4031fbf8ff
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。