使用ReactiveCocoa優(yōu)化實時搜索

需求

在搜索中輸入任何文字,立即聯想到相關的搜索關鍵詞,以列表的方式進行顯示

最簡單的解決方案步驟:

  1. 監(jiān)聽輸入框文字的變化.
  2. 在回調中發(fā)起網絡請求
  3. 將請求的結果顯示出來

問題

  1. 在用戶輸入比較快的情況下,前面幾個請求只是在浪費用戶的流量,因為請求的結果會立即被覆蓋
  2. 由于網絡的不確定性,可能后請求的接口要晚于早請求的結果得到返回結果

使用ReactiveCocoa

針對問題1. 解決的辦法是限流:

    /// 問題1解決
    self.throttleSubject = [RACSubject subject];
    [[self.throttleSubject throttle:1] subscribeNext:^(id x) {
        [self requestWithKeyWord:x];
    }];
    /// 模擬搜索框輸入
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"1"];
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"2"];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"3"];
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"4"];
    });

打印的結果是3,4
原理:在限流的時間內,如果沒有新的數據過來,時間到了,就會sendNext數據,否則,釋放上個計時器(計時器也是個信號,通過dispose進行無效化),重新設置一個新的計時器倒計時
針對問題2.

    /// 問題2解決
    self.requestSignal = [RACSubject subject];
    [self.requestSignal.switchToLatest subscribeNext:^(id x) {
        NSLog(@"請求結果 : %@",x);
    }];

原理:switchToLatest這個信號內部會在收到新的信號時候,將上一個信號進行釋放,也就是說在A,B兩個網絡請求信號,按順序請求的話,如果在B請求前,B請求已經結束,那么,沒有任何問題,這時候搜索的內容和關鍵字肯定還是匹配的,如果B請求的時候,A還沒有sendNext|sendComplete那么,會將A信號進行dispose掉,這樣即使A信號得到數據了也會return掉

- (void)sendNext:(id)value {
    if (self.disposable.disposed) return;
        .......
}

其實這個時候比較好的網絡請求代碼如下

- (RACSignal *)requestWithKeyWord:(NSString *)keyword {
    if (keyword.length == 0) return nil;
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        AFHTTPSessionManager *manager;
        NSURLSessionDataTask *task = [manager POST:nil parameters:nil progress:nil success:nil failure:nil];
        return [RACDisposable disposableWithBlock:^{
            /// 此處可以中斷網絡請求
            [task cancel];
        }];
    }];
}

這樣會使得信號在被新的網絡請求信號沖刷掉的時候,及時終止網絡請求,節(jié)省資源.
完整代碼

- (void)testThrottle {
    /// 問題2解決
    self.requestSignal = [RACSubject subject];
    [self.requestSignal.switchToLatest subscribeNext:^(id x) {
        NSLog(@"請求結果 : %@",x);
    }];

    /// 問題1解決
    self.throttleSubject = [RACSubject subject];
    [[self.throttleSubject throttle:1] subscribeNext:^(id x) {
        NSLog(@"keyword : %@",x);
        [self.requestSignal sendNext:[self requestWithKeyWord:x]];
    }];
    
    /// 模擬搜索框輸入
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"1"];
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"2"];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"3"];
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.throttleSubject sendNext:@"4"];
    });
}

- (RACSignal *)requestWithKeyWord:(NSString *)keyword {
    if (keyword.length == 0) return nil;
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:keyword];
        });
        return nil;
    }];
}
keyword : 3
keyword : 4
請求結果 : 4
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末袱结,一起剝皮案震驚了整個濱河市袜茧,隨后出現的幾起案子,更是在濱河造成了極大的恐慌蹬跃,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钥勋,死亡現場離奇詭異炬转,居然都是意外死亡,警方通過查閱死者的電腦和手機算灸,發(fā)現死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門扼劈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人菲驴,你說我怎么就攤上這事荐吵。” “怎么了赊瞬?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵先煎,是天一觀的道長。 經常有香客問我巧涧,道長薯蝎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任谤绳,我火速辦了婚禮占锯,結果婚禮上,老公的妹妹穿的比我還像新娘缩筛。我一直安慰自己消略,他們只是感情好,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布瞎抛。 她就那樣靜靜地躺著艺演,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胎撤,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天晓殊,我揣著相機與錄音,去河邊找鬼哩照。 笑死挺物,一個胖子當著我的面吹牛,可吹牛的內容都是我干的飘弧。 我是一名探鬼主播识藤,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼次伶!你這毒婦竟也來了痴昧?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤冠王,失蹤者是張志新(化名)和其女友劉穎赶撰,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體柱彻,經...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡豪娜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了哟楷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘤载。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖卖擅,靈堂內的尸體忽然破棺而出鸣奔,到底是詐尸還是另有隱情,我是刑警寧澤惩阶,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布挎狸,位于F島的核電站,受9級特大地震影響断楷,放射性物質發(fā)生泄漏锨匆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一冬筒、第九天 我趴在偏房一處隱蔽的房頂上張望统刮。 院中可真熱鬧,春花似錦账千、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至学搜,卻和暖如春娃善,著一層夾襖步出監(jiān)牢的瞬間论衍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工聚磺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坯台,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓瘫寝,卻偏偏與公主長得像蜒蕾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子焕阿,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內容