搜索功能我相信很多app都用得上,iOS系統(tǒng)提供做搜索的類有那幾種呢?

一、搜索功能我相信很多app都用得上,iOS系統(tǒng)提供做搜索的類有那幾種呢?

1.UISearchBar,這個相信大多數(shù)開發(fā)者都用過,這個只是提供搜索框,其實就是跟一個UITextField沒啥區(qū)別,只是在textfield封裝了多點內(nèi)容。

2.UISearchDisplayController,這個玩意是iOS8之前,專門用來做搜索功能,對的,它就是一個控制器,他為你提供蘋果那種搜索風(fēng)格的轉(zhuǎn)場動畫以及搜索視圖顯示邏輯等,但是使用起來相對復(fù)雜。所以在iOS8這個類已經(jīng)被拋棄了,而引申一個新的搜索類,就是以下要介紹的UISearchController。

3.UISearchController,這個類其實跟UISearchDisplayController功能差不多,只是蘋果對其再進行了高級封裝,從而使用起來更加簡單了。

二、其實自己在搞UISearchController之前,我已經(jīng)到網(wǎng)上找過一下相關(guān)的資料,發(fā)現(xiàn)網(wǎng)上寫的都是千遍一律,教你怎么用,就我個人覺得,難的是你要在它基礎(chǔ)上去對改它的UI,這就要你對它的視圖層次結(jié)構(gòu)要很清楚了,那我們下面來開始干活吧。

我們首先看一下系統(tǒng)自帶的搜索框是怎樣的。

normal狀態(tài)下的searchBar

這個是正常狀態(tài)下的搜索框,但是那灰色的背景真是丑出翔了,試問有那個產(chǎn)品設(shè)計能接受這個樣式的搜索框?我們再看下編輯狀態(tài)下的吧。

編輯無文字狀態(tài)下

從normal到edit狀態(tài)會有一個轉(zhuǎn)場動畫,雖然界面還是很丑,而我們需要的正式這個動畫,如果我們完全自定義的話還需要做這個動畫就未免有點復(fù)雜了。

編輯有文字狀態(tài)

當(dāng)你輸入文字是,你發(fā)現(xiàn)它那個蒙版消失了,而展現(xiàn)新的視圖,沒錯,那個就是你自己的搜索結(jié)果控制器視圖了,下面再詳細(xì)介紹。

三、看了上面幾張圖,我們大概知道UISearchController的交互大概怎樣。

那我們再進去頭文件看一下他的一些屬性和方法吧

它的指定初始化方法就是

```

- (instancetype)initWithSearchResultsController:(nullableUIViewController*)searchResultsController;

```

所以你能定制屬于你自己的搜索結(jié)果view。當(dāng)你傳nil的時候,默認(rèn)是當(dāng)前view就是搜索結(jié)果view。

UISearchResultsUpdating -> 搜索結(jié)果更新回調(diào)的協(xié)議,實現(xiàn)里面的方法就能更新搜索邏輯了,這里不詳細(xì)說,網(wǎng)上一大堆教這個的。

再說下比較常用的屬性吧

```

dimsBackgroundDuringPresentation -> 是否顯示灰色透明的蒙版,默認(rèn)YES

hidesNavigationBarDuringPresentation -> 是否隱藏導(dǎo)航條,這個一般不需要管,都是隱藏的

searchResultsController -> 就是你初始化傳進去的搜索結(jié)果VC

searchBar -> 它內(nèi)部會創(chuàng)建一個搜索框給你。

UISearchController就這幾個屬性了。我們看下先怎么去用?

```

UISearchController *searchController= [[UISearchController alloc] init];

self.tableView.tableHeaderView=searchController.searchBar;

searchController.searchResultsUpdater=self;

searchController.searchBar.delegate=self;

searchController.searchBar.placeholder=@"搜索"; // placeholder

[searchController.searchBar setSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg"] forState:UIControlStateNormal]; // 設(shè)置搜索框內(nèi)部textField的背景圖

[self.searchBar setBackgroundImage:@""] // 設(shè)置搜索框背景圖,要跟上面的區(qū)分哦,兩者不一樣

[searchController.searchBarsetImage:[UIImagehcq_imageNamed:@"business_search_icon"] forSearchBarIcon:UISearchBarIconSearchstate:UIControlStateNormal];// 設(shè)置搜索框內(nèi)放大鏡圖片

searchController.searchBar.tintColor=KC_RGB_COLOR(225,225,225);// 設(shè)置搜索框內(nèi)按鈕文字顏色,以及搜索光標(biāo)顏色。

searchController.searchBar.barTintColor=HCQ_VIEW_BACKGROUND_COLOR;// 設(shè)置搜索框背景顏色

// Get the instance of the UITextField of the search bar

// 用KVC修改placeholder文字顏色

UITextField*searchField = [self.searchBarvalueForKey:@"_searchField"]; // 先取出textfield

// Change the search bar placeholder text color

[searchFieldsetValue:self.searchBar.tintColorforKeyPath:@"_placeholderLabel.textColor"]; // 然后setValueForKey,搞定

[searchController.searchBarsetValue:@"完成"forKey:@"_cancelButtonText"]; // 設(shè)置搜索框那個取消按鈕文字

// 如果你不想要搜索框的背景或者希望背景透明,你加上這句代碼吧

[[[searchController.searchBar.subviews.firstObject subviews] firstObject] removeFromSuperview];// 直接把背景imageView干掉。在iOS8,9是沒問題的,7沒測試過。

```

到這里,UISearchBar的UI就自定義完畢,想了解UISearchBar層次結(jié)構(gòu)的話,可以用Xcode運行后打開那個視圖層次結(jié)構(gòu)看一下就一目了然。

四、下面介紹怎樣定義編輯無文字狀態(tài)下的搜索UI,例如微信點擊搜索框后會出現(xiàn)3個按鈕《朋友圈,文章,公眾號》。

要定義這些UI,那么我們需要自定義一個自己的searchController了,創(chuàng)建一個類MySearchController繼承UISearchController。

首先我們重寫初始化方法

```

- (instancetype)initWithSearchResultsController:(UIViewController*)searchResultsController

{

MyResultViewController *resultVC = [[MyResultViewController ? alloc] init];

if(self= [super initWithSearchResultsController: resultVC]) {

[selfsetup];

}

returnself;

}

- (instancetype)init

{

MyResultViewController *resultVC = [[MyResultViewController?? alloc] init];

if(self= [super initWithSearchResultsController:resultVC]) {

[selfsetup];

}

returnself;

}

// 重寫init方法,好讓外部怎么創(chuàng)建都是我們自己的搜索結(jié)果控制器。外部使用不需要關(guān)心太多

// 可以把剛才自定義SearchBarUI代碼放到內(nèi)部了。

- (void)setup

{

self.searchBar.placeholder=@"搜索商家";

[self.searchBarsetSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg"]forState:UIControlStateNormal];

[self.searchBarsetImage:[UIImagehcq_imageNamed:@"business_search_icon"]forSearchBarIcon:UISearchBarIconSearchstate:UIControlStateNormal];

self.searchBar.tintColor=KC_RGB_COLOR(225,225,225);

self.searchBar.barTintColor=HCQ_VIEW_BACKGROUND_COLOR;

// Get the instance of the UITextField of the search bar

UITextField*searchField = [self.searchBarvalueForKey:@"_searchField"];

// Change the search bar placeholder text color

[searchFieldsetValue:self.searchBar.tintColorforKeyPath:@"_placeholderLabel.textColor"];

[[[self.searchBar.subviews.firstObjectsubviews]firstObject]removeFromSuperview];

[self.searchBarsetValue:@"完成"forKey:@"_cancelButtonText"];

}

```

然后來到viewDidLoad方法,添加我們需要定義的UI。

例如我想加一個switch到中間

```

UISwitch*st = [UISwitch new];

[self.view addSubview:st];

st.center = self.view.center;

```

一般我們會這樣寫,運行后點擊搜索框進入編輯狀態(tài),發(fā)現(xiàn)開關(guān)出來了,但是當(dāng)你輸入文字的時候,開關(guān)還在顯示還能點擊。這就神奇了。會不會是視圖層級不對呢?沒錯,就是視圖層級問題,SearchController.view內(nèi)部還有一個containerView(其實就是那個蒙版),而SearchController是把搜索結(jié)果控制器view添加到containerView上,所以開關(guān)跟containerView是同一層次,而且在containerView之上,所以不會消失。也可以打開層次結(jié)果圖看一下。

我們可以添加一個屬性

```

@property(nonatomic,weak)UIView*containerView;

```

重寫get方法

```

- (UIView*)containerView

{

if(!_containerView) {

_containerView=self.view.subviews.firstObject;

_containerView.backgroundColor=HCQ_VIEW_BACKGROUND_COLOR;

}

return_containerView;

}

```

然后在viewdidload中添加開關(guān)的代碼改一下

```

[self.containerView addSubview:st];

```

繼續(xù)運行,發(fā)現(xiàn)還是不行,還是不會消失,為什么呢?我們知道view的subview有先后順序,后添加的越在上面,因為你的搜索結(jié)果view先添加到containerView,開關(guān)是后面加的,固然開關(guān)還是能看到。所以,你不能直接add,正確姿勢是插入insert

```

[self.containerView insertSubview:st atIndex:0];

```

這樣就沒問題了。

再補充一點,如果你想改containerView的frame,可以在這個方法修改

```

- (void)viewDidLayoutSubviews

{

[super viewDidLayoutSubviews];

}

```

如果想做一些轉(zhuǎn)場過度動畫,那么重寫viewWillAppear、viewWillDisappear在里邊做吧

例如

```

- (void)viewWillAppear:(BOOL)animated

{

[superviewWillAppear:animated];

// 修改textfield背景圖

[self.searchBar setSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg_highlighted"] forState:UIControlStateNormal];

}

- (void)viewWillDisappear:(BOOL)animated

{

[superviewWillDisappear:animated];

// 這里再改回來

[self.searchBar setSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg"]forState:UIControlStateNormal];

}

```

如果當(dāng)狀態(tài)為activity的時候想隱藏tabbar,建議實現(xiàn)UISearchControllerDelegate的代理方法

```

func willPresentSearchController(_searchController:UISearchController) {

tabBarController?.tabBar.isHidden=true

}

func willDismissSearchController(_searchController:UISearchController) {

tabBarController?.tabBar.isHidden=false

}

然后在viewwillAppear將tabbar再次隱藏,否則pop回來的時候又會出現(xiàn)

override func viewWillAppear(_animated:Bool) {

super.viewWillAppear(animated)

if searchController.isActive{

tabBarController?.tabBar.isHidden = true

}

}

```

如果想push的時候把搜索框也跟著隱藏

那么在導(dǎo)航的棧頂控制器寫下

definesPresentationContext = true

必須要在棧頂控制器寫,而且push下一個子控制器的時候也要在導(dǎo)航棧里Push,否則會有莫名其妙的Bug

五、結(jié)語

基本上按照上面所說的就能自定義基于系統(tǒng)的,屬于自己風(fēng)格的搜索框了。用系統(tǒng)提供的轉(zhuǎn)場動畫還是挺好看的。定制起來也比較簡單,有這個需求的可以參考下我寫的這編文章。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容