標籤:
大熊貓豬·侯佩原創或翻譯作品.歡迎轉載,轉載請註明出處.
如果覺得寫的不好請多提意見,如果覺得不錯請多多支援點贊.謝謝! hopy ;)
以前iOS的搜尋一般都使用UISearchDisplayController來完成,不過自從iOS 8.0開始,該控制器被標記為廢棄,我們可以在iOS 8.0之後使用一個新的搜尋控制器UISearchController來完成搜尋.
本篇博文將介紹以上2種搜尋控制器的簡單用法,並比較它們的區別.Let’t Go!
UISearchDisplayController
使用該控制器我們必須給根控制器添加一個UISearchDisplayDelegate協議,然後完成其規定的幾個回調方法:
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{ [_filteredNames removeAllObjects]; if (searchString.length > 0) { NSPredicate *predicate = [NSPredicate predicateWithBlock: ^BOOL(NSString *name,NSDictionary *b) { NSRange range = [name rangeOfString:searchString options:NSCaseInsensitiveSearch]; return range.location != NSNotFound; }]; for (NSString *key in _keys) { NSArray *matchs = [_names[key] filteredArrayUsingPredicate:predicate]; [_filteredNames addObjectsFromArray:matchs]; } } return YES;}-(void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView{ [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:SectionsTableID];}
其中第一個方法在搜尋索引鍵發生改變時調用,後一個則在搜尋表視圖載入完畢後調用,我們可以看見如上代碼所示,我們在搜尋表視圖載入後將其表視圖的UITableViewCell元素的ID和一個特定的ID綁定,這樣做可以重用已存在的儲存格.另外需要注意的是該ID和根視圖控制器中標示圖的儲存格ID是一樣的,雖然這兩個表視圖是不一樣的.
我們在根視圖控制器的didLoadView中用以下代碼初始化UISearchDisplayController:
UISearchBar *searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];tableView.tableHeaderView = searchBar;_searchController = [[UISearchDisplayController alloc]initWithSearchBar:searchBar contentsController:self];_searchController.delegate = self;_searchController.searchResultsDataSource = self;
以上代碼首先建立一個searchBar並將其設定為tableView的表頭視圖,接著以該searchBar為參數建立UISearchDisplayController對象,最後設定好其對應的委託.
因為此時根視圖中存在2個表視圖,所以我們在處理相關回調方法時要區分當前處理的是哪張表視圖:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ if (tableView.tag == 1) { return _keys.count; }else{ return 1; }}
我們將預設的呈現資料的表視圖的tag設定為1,這樣我們就知道當前需要處理的是哪張表視圖了.其它的回調與此類似,不再一一述及.
UISearchController
下面我們來看看iOS 8.0之後新的搜尋器類的使用方法.首先我們也必須添加一個UISearchResultsUpdating協議,同時實現一個協議方法:
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController;
該方法和前一個搜尋器類的方法類似,不過要注意的是它不傳回值,這意味著如果你想要顯示搜尋結果,你必須手動重新整理表視圖.下面給出一個該方法的例子:
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController{ NSString *searchString = _searchController.searchBar.text; [_filteredNames removeAllObjects]; if (searchString.length > 0) { NSPredicate *predicate = [NSPredicate predicateWithBlock: ^BOOL(NSString *name,NSDictionary *b) { NSRange range = [name rangeOfString:searchString options:NSCaseInsensitiveSearch]; return range.location != NSNotFound; }]; for (NSString *key in _keys) { NSArray *matchs = [_names[key] filteredArrayUsingPredicate:predicate]; [_filteredNames addObjectsFromArray:matchs]; } }else{ //如果搜尋索引鍵為空白則顯示所有key for (NSString *key in _keys) { NSArray *matchs = _names[key]; [_filteredNames addObjectsFromArray:matchs]; } } UITableView *tableView = [self.view viewWithTag:1]; //手動重新整理表視圖 [tableView reloadData];}
UISearchController還有一個和UISearchDisplayController不同的地方,就是判斷當前表視圖是否是搜尋表視圖的方法:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ if (_searchController.active) { return 1; }else{ return _keys.count; }}
好吧,我收回上面的話…準確來說,應該是前者根本沒有自己的表視圖,它使用的表視圖就是預設的表視圖.也就是我們必須自預設的表視圖中判斷當前搜尋是否啟用,如果是則顯示搜尋後的結果,否則顯示預設呈現的資料.
最後我們來看看,如何初始化UISearchController:
_searchController = [[UISearchController alloc]initWithSearchResultsController:nil]; _searchController.searchResultsUpdater = self; _searchController.dimsBackgroundDuringPresentation = NO; _searchController.hidesNavigationBarDuringPresentation = NO; tableView.tableHeaderView = _searchController.searchBar;
大家可以看到不用再自己建立UISearchBar對象了,UISearchDisplayController已經幫你搞定了.
總結
最後我們來看一下以上2種搜尋控制器的不同:
- 前者使用單獨的表視圖,後者沒有表視圖,其內容使用預設的表視圖來呈現.
- 前者需要手動建立UISearchBar對象,而後者不需要
- 前者需要在表示圖的協議回調中判斷當前是哪個表視圖,而後者只是簡單判斷搜尋是否處在啟用狀態
- 它們遵守的協議不一樣,協議方法自然也不一樣
- 前者比較複雜,後者更簡單,從類的構成上來說也更合理.
iOS中的2中搜尋方式UISearchDisplayController和UISearchController