解決textDidChange每次都重複發請求

weixin_33866037發表於2016-10-14

專案中很多地方需要搜尋, 每次搜尋都是呼叫服務端提供的介面 . 對這些事情做個總結吧.

Q:

需求如下 ,
使用者點選搜尋欄,跳出鍵盤並輸入,每次輸入完畢, 用另一個tableview展示搜尋結果.

分析:

在iOS中無論是哪一種搜尋, 似乎直接用系統的庫UISearchbar是最簡單的.

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

利用它的回撥方法進行搜尋. 看上去真的很簡單. 哪怕控制元件麻煩一點,用UITextfield這也不會是問題 .

坑來了. 當每次text變化, 都會觸發這個方法 . 如果我在這裡傳送請求, 訪問服務端, 會出現一個問題.

通常使用者打字比較快, 會瘋狂的輸入,這裡就會瘋狂的觸發請求,導致流量,記憶體過渡的浪費了, 效能大大降低, 要重複請求這麼多次, 這肯定是不合理的####


A:

解決思路
把這些請求NSURLSessionDataTask放到一個佇列裡, 每次執行textDidChange方法, 先對這個佇列進行處理, cancel之前的請求.

上程式碼


#import <Foundation/Foundation.h>

typedef void(^BlockSearchTaskComplete)(NSURLSessionDataTask *task, id responseObject) ;

@interface XTSearchHandler : NSObject

@property (nonatomic,copy) BlockSearchTaskComplete searchComplete ;
- (void)searchWithText:(NSString *)searchText ;

@end

@interface XTSearchHandler ()

@property (nonatomic,strong) NSMutableArray *arrayOfTasks ;
@property (nonatomic,strong) AFHTTPSessionManager *manager ;

@end

@implementation XTSearchHandler

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.manager = [[AFHTTPSessionManager alloc] init] ;
        self.manager.responseSerializer = [AFJSONResponseSerializer serializer] ;
        self.arrayOfTasks = [NSMutableArray new] ;

    }
    return self;
}

- (void)searchWithText:(NSString *)searchText
{
    if (searchText.length >= 2)
    {
        /// cancel all previous tasks
        [self.arrayOfTasks enumerateObjectsUsingBlock:^(NSURLSessionDataTask *taskObj, NSUInteger idx, BOOL *stop) {
            [taskObj cancel] ; /// when sending cancel to the task failure: block is going to be called
        }];
        
        /// empty the arraOfTasks
        [self.arrayOfTasks removeAllObjects];
        
        /// init new task
        NSURLSessionDataTask *task = [ServerRequest searchArticleTagWithSearchKey:searchText
                                                                          manager:self.manager
                                                                          success:^(NSURLSessionDataTask *task, id responseObject) {
                                                                              
                                                                              self.searchComplete(task,responseObject) ;
                                                                              
                                                                          } fail:^(NSURLSessionDataTask *task, NSError *error) {
                                                                              
                                                                          }] ;
        
        /// add the task to our arrayOfTasks
        [self.arrayOfTasks addObject:task] ;
    }
}

@end

相關文章