UISearchBar對象做爲一個普通的視圖對象添加到視圖控制器的self.view中,定義、初始化、設置delegate,然後becomeFirstResponder,最後resignFirstResponder。
CGRect searchBarFrame= CGRectMake(0, 0, self.view.frame.size.width, 40);
_searchBar = [[UISearchBar alloc] initWithFrame:searchBarFrame];
[_searchBar setPlaceholder:@"Search"];// 搜索框的佔位符
//[_searchBarsetPrompt:@"Prompt"];// 頂部提示文本,相當於控件的Title
[_searchBar setBarStyle:UIBarStyleDefault];// 搜索框樣式
[_searchBar setTintColor:[UIColor blueColor]];// 搜索框的顏色,當設置此屬性時,barStyle將失效
[_searchBar setTranslucent:YES];// 設置是否透明
//[_searchBarsetShowsCancelButton:YES];// 是否顯示取消按鈕
//[_searchBarsetShowsCancelButton:YES animated:YES];
_searchBar.delegate=self;
[self.view addSubView:_searchBar];
這一切很正常,也很自然。
但是,這裏的應用環境是將searchBar作爲一個uiresponder子類的對象gridview的inputAccessoryView。
這樣他的響應鏈條就複雜了。
我開始在searchBarTextDidBeginEditing方法中將searchBar的cancelButton展現出來,然後在searchBarTextDidEndEditing方法中將cancelButton關閉。
但是,我無論在cancel操作、search操作,及觸摸虛擬鍵盤以外的點以調用視圖控制器上的touchbegin方法,來resignFirstResponder。
這三個調用方法,都能將searchBar的第一響應者resign掉,但就是不能調用searchBarShouldEndEditing。
在整個響應鏈條中,當gridview變成firstResponder時,searchBar做爲inputAccessoryView出現,再觸摸searchBar的搜索框時,firstResponder發生了變化。
gridview不再是firstResponder,searchBar變成了firstResponder。再searchBar進行resignFirstResponder後,gridView又變成了firstResponder。
這個過程理解好,在應用中需要小心處理好這種響應鏈條的傳遞操作。
不知道是不是因爲firstResponder還在,所以沒有調用作爲searchBar的delegate的searchBarTextDidEndEditing方法。
將searchBar的delegate所有方法研究一下,發現還有兩個方法可以用,可以用來實現這種cancelButton隨着firstResponder變化而展現、消失。
這兩個方法是searchBarShouldEndEditing和searchBarShouldEndEditing,在firstResponder變化前都會調用這兩個方法。
在觸摸searchBar的搜索框時,searchBar就變成了firstResponder,那麼在這時,會調用searchBarShouldEndEditing。
在我們將searchBar的firstResponder身份取消時,又會調用searchBarShouldEndEditing。那麼,我們可以在這兩個方法中實現我們要的功能。
結論,關鍵是理解整個響應鏈條。在視圖控制器類中,gridview首先變成firstResponder,再searchBar變成firstResponder。
然後逐步resignFirstResponder,即使在self.view endEditing。也逐步操作。
代碼
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
//無法調用 cancelbuttong 的 關閉功能, 妥協 不用這個吧。
// [_searchBarsetShowsCancelButton:YES animated:YES];
// 發現放到searchBarShouldBeginEditing 方法中也能實現這個功能,
// 在方法searchBarShouldEndEditing 中可以 將 cancelbutton 關閉掉。
}
-(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
[_searchBar setShowsCancelButton:YES animated:YES];
BOOL xx,yy;
xx=[_gridView isFirstResponder];
yy=[_searchBar isFirstResponder];
NSLog(@"_gridView,searchBar %d,%d",xx,yy);
return YES;
}
-(BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
[_searchBar setShowsCancelButton:NO animated:YES];
BOOL xx,yy;
xx=[_gridView isFirstResponder];
yy=[_searchBar isFirstResponder];
NSLog(@"_gridView,searchBar %d,%d",xx,yy);
return YES;
}
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
//無法調用 cancelbuttong 的 關閉功能, 妥協 不用這個吧。
// [_searchBarsetShowsCancelButton:YES animated:YES];
// 發現放到searchBarShouldBeginEditing 方法中也能實現這個功能,
// 在方法searchBarShouldEndEditing 中可以 將 cancelbutton 關閉掉。
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
// 這個方法還是不能被調用,無法解釋。
// [_searchBar setShowsCancelButton:NO animated:YES];
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[_searchBar resignFirstResponder];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
BOOL xx,yy;
xx=[_gridView isFirstResponder];
yy=[_searchBar isFirstResponder];
NSLog(@"_gridView,searchBar %d,%d",xx,yy);
[_searchBar resignFirstResponder];
xx=[_gridView isFirstResponder];
yy=[_searchBar isFirstResponder];
NSLog(@"_gridView,searchBar %d,%d",xx,yy);
// 當 searchbar 不是 first responder時,gridview自動變成了 first responder.
// 所以,searchbar不會變成 end editing,它也就不會調用searchBarTextDidBeginEditing:方法。這是猜測,沒理論根據,也沒得到apple承認,也不是網上看到的文字,純屬個人猜想。
}