標籤:style blog http io ar os 使用 for sp
本文轉載至 http://blog.sina.com.cn/s/blog_74e9d98d01019vji.html
在之前做過的應用中,很多都有“搜尋”這個功能,大部分情況下我都是只採用UISearchBar並結合UItableView來展示搜尋結果,其 實IOS SDK中已經有內建的控制項能協助我們做好這些事,這就是UISearchDisplayController,當然這個控制項也有一些不足之處,下面我就一 一道來。。
首先我先講下UISearchDisplayController的實現原理:
UISearchDisplayController 不是一個viewController,不要被其字面意思給欺騙了,其實它的父類就是NSObject ,它裡面就整合了 一個UISearchBar對象和一個UItableView對象,UISearchBar對象負責展示搜尋輸入框,UItableView對象負責展示 搜尋出來的結果。然後,調用者在外部實現一些UISearchDisplayDelegate中的方法來做一些自訂的處理,這個protocol中有很 多方法,其中最重要的就是
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 此方法擷取使用者輸入的關鍵字searchString,然後開發人員處理出搜尋結果並返回YES,表示重新reload UItableView對象
使用方法:
.h檔案
#import
@interface ViewController : UIViewController{
UISearchDisplayController *searchDisplayController;
NSArray *_searchResults; //存放搜尋結果的數組
}
@property (retain, nonatomic) IBOutlet CustomSearchDisplayController *searchDisplayController;
@property (nonatomic, copy) NSArray *searchResults;
@end
.m檔案:
#pragma mark tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = 0;
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){ //表示當前tableView顯示的是搜尋結果
rows = [self.searchResults count];
}else{
//此處可以展示所有的資料,一般本地搜尋可用到,如“電話簿”
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
}else{
// cell.textLabel.text = [self.allItems objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark - UISearchDisplayController delegate methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
//根據使用者的輸入的關鍵字searchString,處理出搜尋結果(可以是本地搜尋,可以是從伺服器請求過來的資料)到數組
self.searchResults中
return YES; //返回yes,重新載入tableView對象
}
至此,UISearchDisplayController控制項的大致使用方法就是如此了。
不足之處
當使用UISearchDisplayController之後,你是否發現,當鍵盤彈出來的時候,會預設把navagationBar給隱藏起來,如果說不需要隱藏navagationBar,最好的處理方式就是重寫UISearchDisplayController的-(void)setActive:(BOOL)visible animated:(BOOL)animated方法:
首先,自訂一個類CustomSearchDisplayController,繼承自UISearchDisplayController,然後在.m檔案中重寫該方法,並在該方法中主動顯示navagationBar,
#import "CustomSearchDisplayController.h"
@implementation CustomSearchDisplayController
-(void)setActive:(BOOL)visible animated:(BOOL)animated
{
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
}
@end
當沒有匹配的結果時,預設會在tableView上顯示一個“No Result”的標籤,如果說想自訂這個標籤,可以在tableview中迴圈遍曆出該標籤,然後按照你的想法去設定:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString];
if ([filteredListPinYin count] == 0) {
UITableView *tableView1 = self.searchDisplayController.searchResultsTableView;
for( UIView *subview in tableView1.subviews ) {
if( [subview class] == [UILabel class] ) {
UILabel *lbl = (UILabel*)subview; // sv changed to subview.
lbl.text = @”沒有結果”;
}
}
}
// Return YES to cause the search result table view to be reloaded.
return YES;
}
另外,由於UISearchDisplayController裡的UISearchBar對象和UITableView對象都是可訪問的,因此就給我們很多便利可以隨意的更改其在UI上的顯示效果
蘋果對控制項封裝習慣的理解:
之前我做過的控制項封裝,基本上都是繼承自UIView或是UIViewController,這樣自訂出來的控制項通過初始化之後,可以直接add到view中並呈現出來,
但是仔細看看UISearchDisplayController,他並不是一個視圖類的對象,當通過調用初始化函數並指定delegate之後,我突然間陷入了無路之境,我現在已經建立好
UISearchDisplayController對象,我如何把它顯示到我應用的視圖上呢?
研究了一會兒發現,只要把UISearchDisplayController的UISearchBar對象add到應用視圖中就OK了!這就很奇怪了,為什麼它的實現方式與之前自己的
實現不同呢,那之後再顯示搜尋結果的tableview的時候是如何展現到應用視圖中的呢?通過測試發現:
原來UISearchDisplayController的UISearchBar對象初始化之後,預設進行了一些操作,如在UISearchDisplayController中實現UISearchBar的UISearchBarDelegate的相關方法,
以檢測跟蹤使用者的“點擊輸入框”、“搜尋索引鍵的變化”等一系列使用者行為,然後UISearchDisplayController根據這些行為進行“彈出鍵盤”、“顯示搜尋結果tableView”等,而這些響應的
行為它並沒有自己在類中寫死掉,而是通過留出一個delegate給外部,讓外部來實現這些具體的響應行為。至於它是怎樣將結果tableView添加到應用視圖中的,很明顯,
初始化函數:- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController;中有個contentsController變數就是指的應用視圖congtoller,
這樣就明白了。
由此,我們可以發現,蘋果對控制項的封裝是嚴格按照MVC的模式來的,在此處,UISearchDisplayController就是model層,它不是View,他不受View的管制(如初始化後add到應用視圖上),他應該是來管制視圖的,
它只去處理邏輯資料(如擷取使用者輸入的關鍵字並匹配出結果集),所以我們就可以明白了為什麼應用視圖只要add searchBar對象就行了的
嘗試使用UISearchDisplayController及對蘋果對控制項封裝習慣的理解