RAC常用清單

RACSignal:

一:創(chuàng)建方法:

+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe;

+ (RACSignal *)error:(NSError *)error;

+ (RACSignal *)return:(ValueType)value;

+ (RACSignal *)empty;

二:操作相關(guān):

1.timeOut:超時,可以讓一個信號在一定的時間后,自動報錯。

[[[RACSignal createSignal:^RACDisposable *(id subscriber) {

????[[RACScheduler mainThreadScheduler] afterDelay:3?schedule:^{

????????[subscriber sendNext:@"rac"];

????????[subscriber sendCompleted];

????}];

????return?nil;

}] timeout:2?onScheduler:[RACScheduler mainThreadScheduler]]

????subscribeNext:^(id x) {

????//TODO

} error:^(NSError *error) {

????//TODO

} completed:^{

????//TODO

}];

2.then:有兩部分?jǐn)?shù)據(jù):想讓上部分先進(jìn)行網(wǎng)絡(luò)請求但是過濾掉數(shù)據(jù),然后進(jìn)行下部分的,拿到下部分?jǐn)?shù)據(jù)?

// 創(chuàng)建信號A?

RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {?

????NSLog(@"----發(fā)送上部分請求---");?

????[subscriber sendNext:@"上部分?jǐn)?shù)據(jù)"];?

????[subscriber sendCompleted];?// 必須調(diào)用sendCompleted方法!?

????return?nil;?

}];?


// 創(chuàng)建信號B?

RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {?

????// 發(fā)送請求?

????NSLog(@"--發(fā)送下部分請求--");?

????[subscriber sendNext:@"下部分?jǐn)?shù)據(jù)"];?

????[subscriber sendCompleted];?

????return?nil;?

}];?

// 創(chuàng)建組合信號?

RACSignal *thenSignal = [signalA then:^RACSignal *{?

????return?signalB;?

}];?


// 訂閱信號?

[thenSignal subscribeNext:^(id x) {?

????NSLog(@"%@", x);?

}];

3.zipWith:把兩個信號壓縮成一個信號,只有當(dāng)兩個信號同時發(fā)出信號內(nèi)容時,并且把兩個信號的內(nèi)容合并成一個元組,才會觸發(fā)壓縮流的next事件。

RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {

????[subscriber sendNext:@1];

????return?nil;

}];


RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {

????[subscriber sendNext:@2];

????return?nil;

}];


// 壓縮信號A,信號B

RACSignal *zipSignal = [signalA zipWith:signalB];

[zipSignal subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

元組內(nèi)元素的順序不會變,跟發(fā)送的順序無關(guān),而是跟壓縮的順序有關(guān)[signalA zipWith:signalB]---先是A后是B

底層實(shí)現(xiàn):

1.定義壓縮信號,內(nèi)部就會自動訂閱signalA,signalB

2.每當(dāng)signalA或者signalB發(fā)出信號,就會判斷signalA,signalB有沒有發(fā)出個信號,有就會把最近發(fā)出的信號都包裝成元組發(fā)出。

等同于下面的寫法

[[RACSignal combineLatestWith:@[signalA, signalB] subscribeNext:^(id x) {

????//TODO

}];

4.retry重試只要失敗,就會重新執(zhí)行創(chuàng)建信號中的block,直到成功.

__block?int?i =?0;

[[[RACSignal createSignal:^RACDisposable *(id subscriber) {

????if?(i ==?10) {

????????[subscriber sendNext:@1];

????}else{

????????NSLog(@"接收到錯誤");

????????[subscriber sendError:nil];

????}

????i++;

????return?nil;

}] retry] subscribeNext:^(id x) {

????NSLog(@"%@",x);

} error:^(NSError *error) {


}];

5.throttle節(jié)流:在一定時間(1秒)內(nèi),不接收任何信號內(nèi)容,過了這個時間(1秒)獲取最后發(fā)送的信號內(nèi)容發(fā)出

RACSubject *signal = [RACSubject subject];

[[signal throttle:1] subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

[signal sendNext:@"test"];

6.interval定時:每隔一段時間發(fā)出信號(基本上算是rac定時器了)

[[RACSignal interval:1?onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

7.delay:延遲發(fā)送

①RACSignal *signal = [[[RACSignal createSignal:^RACDisposable *(id subscriber) {

????[subscriber sendNext:@1];

????return?nil;

}] delay:2] subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

②[[RACScheduler mainThreadScheduler] afterDelay:2?schedule:^{?

????//TODO?

}];

8.take:從開始一共取N次的信號。takeLast:取最后N次的信號,前提條件,訂閱者必須調(diào)用完成,因?yàn)橹挥型瓿?,就知道總共有多少信?takeUntil:獲取信號直到某個信號執(zhí)行完成

RACSubject *signal = [RACSubject subject];

[[signal take:1] subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

[signal sendNext:@1];

[signal sendNext:@2];

9.concat:有兩部分?jǐn)?shù)據(jù):想讓上部分先執(zhí)行,完了之后再讓下部分執(zhí)行(都可獲取值), 如果A發(fā)送失敗,B也不會執(zhí)行。A和B是依賴關(guān)系

RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {?

????[subscriber sendNext:@"上部分?jǐn)?shù)據(jù)"];?

????[subscriber sendCompleted];?// 必須要調(diào)用sendCompleted方法!?

????return?nil;?

}];?

RACSignal *signalsB = [RACSignal createSignal:^RACDisposable *(id subscriber) {?

????[subscriber sendNext:@"下部分?jǐn)?shù)據(jù)"];?

????return?nil;?

}];?

// concat:按順序去鏈接?

RACSignal *concatSignal = [signalA concat:signalsB];?

// 訂閱組合信號?

[concatSignal subscribeNext:^(id x) {?

????NSLog(@"%@",x);?

}];

10.RAC線程切換

RACScheduler *backgroundScheduler = [RACScheduler scheduler];

RACSignal *testSignal = [[RACSignal

createSignal:^RACDisposable *(id subscriber) {

????// 這段代碼會運(yùn)行在子線程

????[subscriber sendNext:@1];

????[subscriber sendCompleted];

????return?nil;

}]

subscribeOn:backgroundScheduler];

[[testSignal deliverOn: [RACScheduler mainThreadScheduler]] subscribeNext:^(id _Nullable x) {

????NSLog(@"在主線程執(zhí)行");

}];

takeLast表示倒數(shù)的前兩次

接下來是幾個block回調(diào)方法

takeWhileBlock BOOL值,意思是當(dāng)返回YES的時候,訂閱者才能收到信號

skipWhileBlock BOOL值,意思是當(dāng)返回YES的時候,訂閱者就會跳過信號,NO的時候才接受

skipUntilBlock BOOL值,意思是 返回NO的時候,不會收到消息, 直到返回YES的時候才開始收消息。

distinctUntilChanged 表示兩個消息相同的時候,只會發(fā)送一個請求

11.merge: 把多個信號合并為一個信號,任何一個信號有新值的時候就會調(diào)用

RACSubject *signalA = [RACSubject subject];

RACSubject *signalB = [RACSubject subject];

RACSignal *signals = [signalA merge:signalB];

[signals subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

[signalA sendNext:@1];

[signalB sendNext:@2];

[signalB sendNext:@3];

12.combineLatest: reduce:把validUsernameSignal和validPasswordSignal產(chǎn)生的最新的值聚合在一起,并生成一個新的信號。每次這兩個源信號的任何一個產(chǎn)生新值時,reduce block都會執(zhí)行,block的返回值會發(fā)給下一個信號

RACSignal *signUpActiveSignal =

[RACSignal combineLatest:@[validUsernameSignal, validPasswordSignal]

reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid) {

????return?@([usernameValid boolValue] && [passwordValid boolValue]);

}];

combineLatest:將多個信號合并起來,并且拿到各個信號的最新的值,必須每個合并的signal至少都有過一次sendNext,才會觸發(fā)合并的信號。

reduce聚合:用于信號發(fā)出的內(nèi)容是元組,把信號發(fā)出元組的值聚合成一個值。reduceblcok中的參數(shù),有多少信號組合,reduceblcok就有多少參數(shù),每個參數(shù)就是之前信號發(fā)出的內(nèi)容

reduceblcok的返回值:聚合信號之后的內(nèi)容。

rac_liftSelector:withSignals 也是類似,當(dāng)signalA和signalB都至少sendNext過一次,接下來只要其中任意一個signal有了新的內(nèi)容,相應(yīng)方法就會自動被調(diào)用。

13.skip:表示輸入第幾次,不會被監(jiān)聽到,跳過第幾次發(fā)出的信號

[[_textField.rac_textSignal skip:1] subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

14.distinctUntilChanged:過濾,當(dāng)上一次和當(dāng)前的值不一樣,就會發(fā)出內(nèi)容

[[_textField.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

15.filter:過濾信號,使用它可以獲取滿足條件的信號

[_textField.rac_textSignal filter:^BOOL(NSString *value) {

????return?value.length >?3;

}];

16.ignore:忽略某些值的信號

[[_textField.rac_textSignal ignore:@"1"] subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

17.startWith:startWith:@"123"等同于[subscriber sendNext:@"123"] 也就是第一個發(fā)送

RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id subscriber) {

????//[subscriber sendNext:@"123"];//startWith:@"123"等同于這句話

????[subscriber sendNext:@"rac"];

????[subscriber sendCompleted];

????return?nil;

}] startWith:@"123"];

[signal subscribeNext:^(id x) {


}];

18.switchToLatest:只能用于signalOfSignals(信號的信號)

RACSubject *signalOfSignals = [RACSubject subject];

RACSubject *signal = [RACSubject subject];

[signalOfSignals.switchToLatest subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

[signalOfSignals sendNext:signal];

[signal sendNext:@1];

19.

doNext: 執(zhí)行Next之前,會先執(zhí)行這個Block

doCompleted: 執(zhí)行sendCompleted之前,會先執(zhí)行這個Block

[[[[RACSignal createSignal:^RACDisposable *(id subscriber) {

????[subscriber sendNext:@1];

????[subscriber sendCompleted];

????return?nil;

}] doNext:^(id x) {

????// 執(zhí)行[subscriber sendNext:@1];之前會調(diào)用這個Block

}] doCompleted:^{

????// 執(zhí)行[subscriber sendCompleted];之前會調(diào)用這個Block

}]];

一個頁面多個網(wǎng)絡(luò)請求:

①rac_liftSelector:withSignalsFromArray:Signals:當(dāng)傳入的Signals(信號數(shù)組),每一個signal都至少sendNext過一次,就會去觸發(fā)第一個selector參數(shù)的方法

RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id subscriber) {?

????[subscriber sendNext:@"發(fā)送請求1"];?

????return?nil;?

}];?

RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id subscriber) {?

????[subscriber sendNext:@"發(fā)送請求2"];?

????return?nil;?

}];?

// 使用注意:幾個信號,參數(shù)一的方法就幾個參數(shù),每個參數(shù)對應(yīng)信號發(fā)出的數(shù)據(jù)。?

[self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];

②接口串聯(lián)?

@weakify(self)

RACSignal *finalSignal = [[self fetchData]

flattenMap:^RACSignal *(NSString *dataResult) {

????@strongify(self)

????return?[self fetchData2:dataResult];

}];

RACCommand篇:

一般用于:1:button點(diǎn)擊 2:包裝網(wǎng)絡(luò)請求接口

一: RACCommand的創(chuàng)建有兩種形式:

- (id)initWithSignalBlock:(RACSignal * (^)(id input))signalBlock;?

- (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock;

注意:

1.伴隨著command一起構(gòu)建的signal,記得要在操作完成后發(fā)送完成消息以表示其執(zhí)行完了,[subscriber sendCompleted];否則不能再執(zhí)行此command。

2.UIButton中有屬性rac_command用于綁定一個已經(jīng)創(chuàng)建好的command,當(dāng)使用第二種方式創(chuàng)建command時,button的enable屬性會隨command的可執(zhí)行性而改變,意思是當(dāng)傳遞布爾事件的信號傳遞了真值事件,按鈕才可使用。另外,當(dāng)你按下按鈕,command開始執(zhí)行時,按鈕的enable被自動設(shè)置成了NO,除非command執(zhí)行完了。

3.當(dāng)button的rac_command已經(jīng)綁定了某個command,而這個command又是以第二種方式初始化,那么你就不能動態(tài)改變button的enable,如:RAC(self.button, enable) = someSignal;這樣子運(yùn)行起來會報錯。

二:執(zhí)行RACCommand:

- (RACSignal *)execute:(id)input;

三:訂閱RACCommand:

[[[command executionSignals] switchToLatest]

subscribeNext:^(id x) {

????// TODO

}];

四:在對command進(jìn)行錯誤處理的時候,不使用subscribeError:對command的executionSignals進(jìn)行錯誤的訂閱,executionSignals這個信號是不會發(fā)送error事件的,當(dāng)command包裹的信號發(fā)送error事件時,用到command的一個屬性:errors,可以對錯誤進(jìn)行訂閱:

[command.errors

subscribeNext:^(NSError *x) {

????//TODO

}];

也可以通過executing屬性判斷是否正在執(zhí)行

注意事項(xiàng)篇:

1.RACSignal *signalReplay = signal.replay;?

實(shí)現(xiàn)多個訂閱者沒有副作用的效果?

2.RACSubject和RACReplaySubject的區(qū)別

RACSubject必須要先訂閱信號之后才能發(fā)送信號,而RACReplaySubject可以先發(fā)送信號后訂閱

3.避免副作用效果處理(RACMulticastConnection)

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {?

????NSLog(@"發(fā)送請求");?

????[subscriber sendNext:@"ws"];?

????return?nil;?

}];?

RACMulticastConnection *connection = [signal publish];?

[connection.signal subscribeNext:^(id x) {?

????NSLog(@"%@", x);?

}];?

[connection.signal subscribeNext:^(id x) {?

????NSLog(@"%@", x);?

}];?

[connection.signal subscribeNext:^(id x) {?

????NSLog(@"%@", x);?

}];?

[connection connect];

4.RACObserve默認(rèn)會含有self,所以在RAC block內(nèi)使用RACObserve時一定要用@weakify(self);@strongify(self);處理,否則會導(dǎo)致內(nèi)存泄漏

5.RACSubject被map之后 在發(fā)送next信號時一定要發(fā)送complete方法,否則會導(dǎo)致內(nèi)存泄漏。所以不管任何場景下都要sendComplete/sendError

6.ViewModel里用來保存數(shù)據(jù)的數(shù)組,不能使用NSMutableArray。原因是RAC是基于KVO的,而NSMutableArray的Add和Remove方法并不會給KVO發(fā)送通知,因此對NSMutableArray進(jìn)行RACObserve時,并不會達(dá)到我們想要的結(jié)果。(同理其他Mutable的也都不能用)

7.flattenmap與map的區(qū)別是: block中返回的東西不同,flattenmap返回的是signal信號。flattenMap方法,實(shí)際上是根據(jù)前一個信號傳遞進(jìn)來的參數(shù)重新建立了一個信號,這個參數(shù),可能會在創(chuàng)建信號的時候用到,也有可能根本用不到。

8.RACScheduler RAC中的隊(duì)列,用GCD封裝的

9.RACBehaviorSubject最重要的特性就是在訂閱時,向最新的訂閱者發(fā)送之前的消息,RACReplaySubject 相當(dāng)于一個自帶 buffer 的 RACBehaviorSubject,它可以在每次有新的訂閱者訂閱之后發(fā)送之前的全部消息。

10.deliverOn: 內(nèi)容傳遞切換到制定線程中,副作用在原來線程中。

subscribeOn: 內(nèi)容傳遞和副作用都會切換到制定線程中。

11.熱信號是主動的,即使你沒有訂閱事件,它仍然會時刻推送。而冷信號是被動的,只有當(dāng)你訂閱的時候,它才會發(fā)送消息。熱信號可以有多個訂閱者,是一對多,而冷信號只能一對一,當(dāng)有不同的訂閱者,消息會從新完整發(fā)送。

替換原生方法:

1.NSData

rac_readContentsOfURL: options: scheduler: 比oc多出線程設(shè)置

2.NSDictionary

rac_keySequence key 集合

rac_valueSequence value 集合

3.RACTuple元組

RACTuple *tuple = RACTuplePack(@1,@2,@4);?

// 宏的參數(shù)類型要和元組中元素類型一致, 右邊為要解析的元組。?

RACTupleUnpack_(NSNumber *num1, NSNumber *num2, NSNumber * num3) = tuple;?

NSLog(@"%@ %@ %@", num1, num2, num3);

4.代理?

①之前都是需要通過代理監(jiān)聽,給紅色View添加一個代理屬性,點(diǎn)擊按鈕的時候,通知代理做事情?

rac_signalForSelector:把調(diào)用某個對象的方法的信息轉(zhuǎn)換成信號,就要調(diào)用這個方法,就會發(fā)送信號。?

這里表示只要redV調(diào)用btnClick:就會發(fā)出信號,訂閱就好了。

[[redV rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {?

????NSLog(@"點(diǎn)擊紅色按鈕");?

}];

[[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple * tuple) {

????//TODO

}];

eg:

@weakify(self)

self.proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UITextFieldDelegate)];

[[self.proxy rac_signalForSelector:@selector(textFieldShouldReturn:)]

subscribeNext:^(id x) {

????@strongify(self)

}];

self.nameText.delegate = (id)self.proxy;

5.KVO

[[redV rac_valuesAndChangesForKeyPath:@"center"?options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {?

????NSLog(@"%@",x);?

}];

②RACObserve(<#TARGET#>, <#KEYPATH#>)

6.監(jiān)聽事件

[[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {?

????NSLog(@"按鈕被點(diǎn)擊了");?

}];

7.通知

[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {?

????NSLog(@"鍵盤彈出");?

}];

8.手勢

UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] init];

[[tap rac_gestureSignal] subscribeNext:^(UITapGestureRecognizer * tap) {

????//TODO

}];

[self.view addGestureRecognizer:tap];

9.遍歷數(shù)組

NSArray *numbers = @[@1,@2,@3,@4];

[numbers.rac_sequence.signal subscribeNext:^(id x) {

????NSLog(@"%@",x);

}];

10.遍歷字典,遍歷出來的鍵值對會包裝成RACTuple

NSDictionary *dict = @{@"name":@"xmg",@"age":@18};

[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {

????// 解包元組,會把元組的值,按順序給參數(shù)里面的變量賦值

????RACTupleUnpack(NSString *key,NSString *value) = x;

????// 相當(dāng)于以下寫法

????// NSString *key = x[0];

????//NSString *value = x[1];

????NSLog(@"%@ %@",key,value);

}];

雙向綁定:

RAC(<#TARGET, ...#>)//單向綁定

RACChannelTo(<#TARGET, ...#>)//雙向綁定

RACChannelTo(self, filmType, @(ASHRecipeFilmTypeColourNegative)) 第三個參數(shù)是指,如果值的變化中出現(xiàn) nil,那么就會使用這個值來代替,相當(dāng)于一個默認(rèn)值。

RACChannelTo用的是RACKVOChannel實(shí)現(xiàn)的

eg:

RACChannelTo(self.someLabel, text) = RACChannelTo(self.viewModel, someProperty);

[self.textField.rac_newTextChannel subscribe:self.viewModel.someChannel];

[self.viewModel.someChannel subscribe:self.textField.rac_newTextChannel];

RACChannelTo(self, reviewID) = self.viewModel.someChannel;


[self.textField.rac_newTextChannel subscribe:self.anotherTextField.rac_newTextChannel];

[self.anotherTextField.rac_newTextChannel subscribe:self.textField.rac_newTextChannel];



[[RACKVOChannel alloc] initWithTarget:view keyPath:@"property"?nilValue:nil][@"followingTerminal"]?

= [[RACKVOChannel alloc] initWithTarget:model keyPath:@"property"?nilValue:nil][@"followingTerminal"];

與RACChannelTo(view, property) = RACChannelTo(model, property);等價

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

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

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