項(xiàng)目中很多地方需要搜索, 每次搜索都是調(diào)用服務(wù)端提供的接口 . 對(duì)這些事情做個(gè)總結(jié)吧.
Q:
需求如下 ,
用戶點(diǎn)擊搜索欄,跳出鍵盤并輸入,每次輸入完畢, 用另一個(gè)tableview展示搜索結(jié)果.
分析:
在iOS中無(wú)論是哪一種搜索, 似乎直接用系統(tǒng)的庫(kù)UISearchbar是最簡(jiǎn)單的.
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
利用它的回調(diào)方法進(jìn)行搜索. 看上去真的很簡(jiǎn)單. 哪怕控件麻煩一點(diǎn),用UITextfield這也不會(huì)是問(wèn)題 .
坑來(lái)了. 當(dāng)每次text變化, 都會(huì)觸發(fā)這個(gè)方法 . 如果我在這里發(fā)送請(qǐng)求, 訪問(wèn)服務(wù)端, 會(huì)出現(xiàn)一個(gè)問(wèn)題.
通常用戶打字比較快, 會(huì)瘋狂的輸入,這里就會(huì)瘋狂的觸發(fā)請(qǐng)求,導(dǎo)致流量,內(nèi)存過(guò)渡的浪費(fèi)了, 性能大大降低, 要重復(fù)請(qǐng)求這么多次, 這肯定是不合理的####
A:
解決思路
把這些請(qǐng)求NSURLSessionDataTask放到一個(gè)隊(duì)列里, 每次執(zhí)行textDidChange方法, 先對(duì)這個(gè)隊(duì)列進(jìn)行處理, cancel之前的請(qǐng)求.
上代碼
#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