欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ReactiveCocoa代碼實踐之-更多思考

 更新時間:2016年04月20日 10:58:32   作者:董鉑然  
這篇文章主要介紹了ReactiveCocoa代碼實踐之-更多思考的相關資料,需要的朋友可以參考下

相關閱讀:

ReactiveCocoa代碼實踐之-UI組件的RAC信號操作

ReactiveCocoa代碼實踐之-RAC網絡請求重構

1. RACObserve()宏形參寫法的區(qū)別

之前寫代碼考慮過 RACObserve(self.timeLabel , text) 和 RACObserve(self , timeLabel.text) 的區(qū)別。 因為這兩種方法都是觀察self.timeLabel.text的屬性,并且都能實現功能。估計是作者原本用的其中一種后來對另一種也提供了支持,究竟有什么區(qū)別哪一種寫法更好?

點進去看RACObserve的源碼 大多都是方法調用,一層一層點進去最后來到這個方法。

- (RACDisposable *)rac_observeKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)weakObserver block:(void (^)(id, NSDictionary *, BOOL, BOOL))block 

這個方法里面把逗號后面的keypath通過“.” 進行分割成了一個數組。 并且得到三個屬性

BOOL keyPathHasOneComponent = (keyPathComponents.count == );
NSString *keyPathHead = keyPathComponents[];
NSString *keyPathTail = keyPath.rac_keyPathByDeletingFirstKeyPathComponent; 

這里會取到keypatch的頭和去掉頭的部分,并且會在下面方法內部自己調用自己

// Adds the callback block to the remaining path components on the value. Also
// adds the logic to clean up the callbacks to the firstComponentDisposable.
void (^addObserverToValue)(NSObject *) = ^(NSObject *value) {
RACDisposable *observerDisposable = [value rac_observeKeyPath:keyPathTail options:(options & ~NSKeyValueObservingOptionInitial) observer:weakObserver block:block];
[firstComponentDisposable() addDisposable:observerDisposable];
};

并且把keyPathTail 作為keypatch傳進去了,就是遞歸調用,每一次進來都會切掉第一個元素,直到BOOL keyPathHasOneComponent 這個值等于yes。從這個角度看用RACObserve(self , timeLabel.text) 這種寫法會引發(fā)遞歸調用,性能不如RACObserve(self.timeLabel.text)。

2.集合操作

假設現在有一個需求,有一串密碼的數組,我們判斷密碼長度小于6位就是太短,就會系統(tǒng)內部拋出一個消息:XXX密碼太短不合格。采用RAC的寫法會比常規(guī)寫法方便,一個過濾一個自定義然后直接返回。

NSArray *pwds = @[@"",@"",@"",@""];
RACSequence *results = [[pwds.rac_sequence
filter:^ BOOL (NSString *pwd) {
return pwd.length < ;
}]map:^id(NSString *pwd) {
return [[pwd mutableCopy]stringByAppendingString:@"密碼太短不合格"];
}];
NSLog(@"%@",results.array); 

中間filter方法的block內代碼會在下面results.array代碼執(zhí)行時才會執(zhí)行, 相當于是有了個訂閱者才會執(zhí)行。這一點和RACSignal很像,因為signal 和 sequence 都是streams,他們共享很多相同的方法signal是push驅動的stream,sequence是pull驅動的stream。

如果相從RACSequence對象中取出其他屬性時進行操作也可以用如下方法

RACSequence *s = [RACSequence sequenceWithHeadBlock:^id{
return @"自定義操作";
} tailBlock:^RACSequence *{
return [RACSequence new];
}];
NSLog(@"%@",s.head);
NSLog(@"%@",s.tail); 

兩個block分別會在指定屬性被調用時才會執(zhí)行,注意head就是sequence的第一個元素,而tail是除去第一個元素的剩余所有,所以還是一個sequence。(董鉑然博客園)

3.信號實現游戲技能釋放

假設現在需要用RAC模擬一個街機里放爆氣技能的方法。 按下了指定的按鈕順序下前下前拳就會釋放絕招。

首先需要將各個按鈕連線,并設置一個信號來監(jiān)聽所有按鍵單獨信號的并集,捕捉到每個按鈕的title。

// 把六個按鍵的信號合并
RACSignal *comboSignal = [[RACSignal merge:@[
[self.topBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.bottomBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.leftBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.rightBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.BBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.ABtn rac_signalForControlEvents:UIControlEventTouchUpInside]]]
map:^id(UIButton *btn) {
return btn.currentTitle;
}]; 

然后對這個信號源進行buffer操作,把每三秒收到的所有按鍵信息都捕獲到,并進行判斷和后繼操作

// 設置觸發(fā)爆氣條件
NSString *comboCode = @"下前下前拳";
// 實際操作
RACSignal *canAction = [[[comboSignal bufferWithTime: onScheduler:[RACScheduler mainThreadScheduler]] map:^id(RACTuple *value) {
return [[value allObjects] componentsJoinedByString:@""];
}] map:^id(NSString *value) {
return @([value containsString:comboCode]);
}];
// 調用combo:方法就是技能釋放
[self rac_liftSelector:@selector(combo:) withSignalsFromArray:@[canAction]]; 

上面的代碼可以實現預計的功能,只要你能在三秒的buffer內按出指定的按鍵就能釋放。但是用這個方法中間也有一個問題:設置了buffer3秒后這個block里面每隔三秒才會來到一次,也就是說如果你在0.5秒內就按出了技能,那也需要再等2.5秒才能放出技能,顯然這個在實戰(zhàn)中是不能接受的。

于是嘗試了其他的實現思路,嘗試了takeLast:及takeUntilBlock:及scanWithStart: 等方法都不是很合適,最后使用了aggregateWithStart: 達到了需求的目的。

// 設置觸發(fā)爆氣條件
NSString *comboCode = @"下前下前拳";
// 實際操作
_time = [[[NSDate alloc] init] timeIntervalSince1970];
[[comboSignal aggregateWithStart:@"" reduce:^id(NSString* running, NSString* next) {
if (([[[NSDate alloc] init] timeIntervalSince1970] - _time) < 3){
NSString *str = [NSString stringWithFormat:@"%@%@",running,next];
return [str containsString:comboCode]?[self combo]:str;
}
_time = [[[NSDate alloc] init] timeIntervalSince1970];
return str.length < combo.length ? str : [str subStringFromIndex:str.length - comboCode.length];
}]subscribeNext:^(id x){
}]; 

使用這段代碼可以在滿足之前條件的前提下,并且按鈕一按完馬上觸發(fā)技能。

aggregateWithStart:reduce:的第一個參數是初始值,第二個參數是一個block,這個block的返回值就是下一次來到這個block的 running參數。我在這個block的循環(huán)中做的操作有:

1.對時間進行delta計算,如果距離上一次時間節(jié)點大于3秒,刷新時間節(jié)點重新計時。 str小于5則返回,大于5則截取后五位返回。

2.如果小于3秒則把每次按鍵信息聚合成一個字符串并判斷是否包含技能觸發(fā)代碼。

3.滿足的話觸發(fā)技能,技能方法的內部也刷新了時間節(jié)點,并截取running(保留最后4位,防止上一個循環(huán)結束和下一個循環(huán)開始所滿足的條件)。不滿足則將這個字符串繼續(xù)返回。

雖然代碼寫的不是很好看,但是功能是實現了,感覺有點別扭,因為函數式編程倡導的是引用透明無副作用,所以上面需要記錄值和成員變量的做法很明顯就不適合用RAC了,應該還會有更好的方法實現。

4.其他RAC操作

1)映射:flattenMap,Map用于把源信號內容映射成新的內容

2)組合:concat:按一定順序拼接信號,當多個信號發(fā)出的時候,有順序的接收信號

3)`then`:用于連接兩個信號,當第一個信號完成,才會連接then返回的信號

4)`merge`:把多個信號合并為一個信號,任何一個信號有新值的時候就會調用

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

6)`reduce`聚合:用于信號發(fā)出的內容是元組,把信號發(fā)出元組的值聚合成一個值

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

8) ignore:忽略完某些值的信號.

9) distinctUntilChanged:當上一次的值和當前的值有明顯的變化就會發(fā)出信號,否則會被忽略掉

10) take:從開始一共取N次的信號

11)takeLast:取最后N次的信號,前提條件,訂閱者必須調用完成,因為只有完成,就知道總共有多少信號

12)takeUntil:(RACSignal *):獲取信號直到某個信號執(zhí)行完成

13)skip:(NSUInteger):跳過幾個信號,不接受

14)switchToLatest:用于signalOfSignals(信號的信號),有時候信號也會發(fā)出信號,會在signalOfSignals中,獲取signalOfSignals發(fā)送的最新信號

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

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

17)deliverOn: 內容傳遞切換到制定線程中,副作用在原來線程中,把在創(chuàng)建信號時block中的代碼稱之為副作用

18)subscribeOn: 內容傳遞和副作用都會切換到制定線程中

19)interval 定時:每隔一段時間發(fā)出信號

20)delay 延遲發(fā)送next。

21) 代替代理:

•rac_signalForSelector:用于替代代理。

22) 代替KVO :

•rac_valuesAndChangesForKeyPath:用于監(jiān)聽某個對象的屬性改變。

23) 監(jiān)聽事件:

•rac_signalForControlEvents:用于監(jiān)聽某個事件。

24) 代替通知:

•rac_addObserverForName:用于監(jiān)聽某個通知。

25) 監(jiān)聽文本框文字改變:

•rac_textSignal:只要文本框發(fā)出改變就會發(fā)出這個信號。

26) 處理當界面有多次請求時,需要都獲取到數據時,才能展示界面

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

•使用注意:幾個信號,參數一的方法就幾個參數,每個參數對應信號發(fā)出的數據

RAC曾經被冠以 學習成本搞,可讀性差,debug的噩夢等不良評價,但隨著近幾年的演變已逐漸被企業(yè)級項目所接受,并且成為函數響應式編程主流框架。RAC用人越來越多,隨筆和博客也越來越多,學習的門檻已經大大降低。 并且我覺得初學者沒有必要一開始就把所有操作和概念都弄懂,可以從簡單的用法開始一步步的接觸高階語法,這樣會更容易接受。

以上所述是小編給大家介紹的ReactiveCocoa代碼實踐之-更多思考,希望對大家有所幫助!

相關文章

  • 利用Android畫圓弧canvas.drawArc()實例詳解

    利用Android畫圓弧canvas.drawArc()實例詳解

    這篇文章主要給大家介紹了關于利用Android畫圓弧canvas.drawArc()的相關資料,文中通過示例代碼介紹的非常詳細,對大家的理解和學習具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-11-11
  • android 設置wallpaper的操作方法

    android 設置wallpaper的操作方法

    下面小編就為大家?guī)硪黄猘ndroid 設置wallpaper的操作方法。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Android中實現多行、水平滾動的分頁的Gridview實例源碼

    Android中實現多行、水平滾動的分頁的Gridview實例源碼

    如果單行水平滾動,可以用Horizontalscrollview實現。如果是多行水平滾動,則結合Gridview(一般是垂直滾動的)和Horizontalscrollview實現
    2013-06-06
  • Android Studio 代碼導航快捷鍵

    Android Studio 代碼導航快捷鍵

    這篇文章主要介紹了Android Studio 代碼導航快捷鍵的相關資料,需要的朋友可以參考下
    2018-03-03
  • 仿網易新聞客戶端頭條ViewPager嵌套實例

    仿網易新聞客戶端頭條ViewPager嵌套實例

    正確使用requestDisallowInterceptTouchEvent(boolean flag)方法,下面為大家介紹下外層ViewPager布局的實例,感興趣的朋友可以參考下哈
    2013-06-06
  • Kotlin?launch原理全面分析

    Kotlin?launch原理全面分析

    在Android開發(fā)中,launch是我們經常用的,今天來看看它是什么原理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-11-11
  • 基于TransactionTooLargeException異常分析

    基于TransactionTooLargeException異常分析

    下面小編就為大家分享一篇基于TransactionTooLargeException異常分析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-11-11
  • Android FFmpeg音視頻解碼播放示例詳解

    Android FFmpeg音視頻解碼播放示例詳解

    這篇文章主要為大家介紹了Android FFmpeg音視頻解碼播放示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Android精確測量文本寬高及基線位置的方法

    Android精確測量文本寬高及基線位置的方法

    這篇文章主要給大家介紹了關于Android精確測量文本寬高及基線位置的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-08-08
  • Android DrawerLayout帶有側滑功能的布局類(1)

    Android DrawerLayout帶有側滑功能的布局類(1)

    這篇文章主要為大家詳細介紹了Android DrawerLayout帶有側滑功能的布局類,感興趣的小伙伴們可以參考一下
    2016-07-07

最新評論