在之前的一片文章UISearchController中介紹了
UISearchController
的使用弛秋,可以看到其中涉及到很多的委托,在使用UISearchController
的時候需要導(dǎo)入相關(guān)的協(xié)議,設(shè)置代理蝙搔,然后實現(xiàn)協(xié)議中的方法。每次都這樣寫還是比較麻煩的。所以可以對UISearchController
做一次封裝毯欣。將遵循協(xié)議、設(shè)置代理臭脓、實現(xiàn)方法這套流程放在UISearchController
的子類中來實現(xiàn)酗钞,子類對外暴露一組Block
屬性。這樣代理方法的要實現(xiàn)的功能就可以通過Block
來完成啦。
YBSearchController.h文件
#import <UIKit/UIKit.h>
@interface YBSearchController : UISearchController
/**
設(shè)置是否一直顯示搜索結(jié)果頁面
*/
@property (nonatomic) BOOL alwaysShowResultsViewController;
/**
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
*/
@property (nonatomic,copy) void(^updateSearchResultsForSearchController)(UISearchController *searchController);
/**
- (void)willPresentSearchController:(UISearchController *)searchController
*/
@property (nonatomic,copy) void(^willPresentSearchController)(UISearchController *searchController);
/**
- (void)didPresentSearchController:(UISearchController *)searchController
*/
@property (nonatomic,copy) void(^didPresentSearchController)(UISearchController *searchController);
/**
- (void)willDismissSearchController:(UISearchController *)searchController
*/
@property (nonatomic,copy) void(^willDismissSearchController)(UISearchController *searchController);
/**
- (void)didDismissSearchController:(UISearchController *)searchController
*/
@property (nonatomic,copy) void(^didDismissSearchController)(UISearchController *searchController);
/**
- (void)presentSearchController:(UISearchController *)searchController
*/
@property (nonatomic,copy) void(^presentSearchController)(UISearchController *searchController);
/**
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
*/
@property (nonatomic,copy) void(^searchBarSearchButtonClicked)(UISearchBar *searchBar);
/**
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
*/
@property (nonatomic,copy) void(^searchBarCancelButtonClicked)(UISearchBar *searchBar);
@end
YBSearchController.m文件
#import "YBSearchController.h"
@interface YBSearchController ()<UISearchControllerDelegate,UISearchResultsUpdating,UISearchBarDelegate>
@end
@implementation YBSearchController
- (void)dealloc
{
@try
{
// 此處可能多次刪除KVO導(dǎo)致崩潰砚作,目前沒有找到更好的解決辦法所以使用@try @catch 語句塊防止程序崩潰
if (self.alwaysShowResultsViewController && self.searchResultsController) {
[self.searchResultsController.view removeObserver:self forKeyPath:@"hidden"];
}
}
@catch (NSException *e) {
NSLog(@"刪除KVO報錯");
NSLog(@"%@",e);
}
}
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = self;
self.searchBar.delegate = self;
self.searchResultsUpdater = self;
if (self.alwaysShowResultsViewController && self.searchResultsController) {
[self.searchResultsController.view addObserver:self forKeyPath:@"hidden" options:0 context:NULL];
}
}
// 監(jiān)聽 self.searchController.searchResultsController.view 的hidden屬性窘奏,讓搜索結(jié)果頁面一直顯示
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ( object == self.searchResultsController.view && [keyPath isEqualToString:@"hidden"] && self.searchResultsController.view.hidden && self.searchBar.isFirstResponder )
{
self.searchResultsController.view.hidden = NO;
}
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
self.updateSearchResultsForSearchController ? self.updateSearchResultsForSearchController(self) : nil;
}
- (void)willPresentSearchController:(UISearchController *)searchController
{
self.willPresentSearchController ? self.willPresentSearchController(self) : nil;
}
- (void)didPresentSearchController:(UISearchController *)searchController
{
self.didPresentSearchController ? self.didPresentSearchController(self) : nil;
}
- (void)willDismissSearchController:(UISearchController *)searchController
{
self.willDismissSearchController ? self.willDismissSearchController(self) : nil;
}
- (void)didDismissSearchController:(UISearchController *)searchController
{
self.didDismissSearchController ? self.didDismissSearchController(self) : nil;
}
- (void)presentSearchController:(UISearchController *)searchController
{
self.presentSearchController ? self.presentSearchController(self) : nil;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
self.searchBarSearchButtonClicked ? self.searchBarSearchButtonClicked(self.searchBar) : nil;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
self.searchBarCancelButtonClicked ? self.searchBarCancelButtonClicked(searchBar) : nil;
}
@end
注意點
YBSearchController
是UISearchController
的子類。所以使用方法與UISearchController
的使用方法一樣葫录,只是在需要使用UISearchController的代理方法的時候改成了我們封裝的Block屬性來實現(xiàn)蔼夜。在上面的YBSearchController.m方法中我們可以看到為了讓搜索結(jié)果頁面
searchResultsController
一直顯示我們使用到了KVO技術(shù)。來監(jiān)聽searchResultsController.view
的hidden
屬性并在監(jiān)聽的回調(diào)方法observeValueForKeyPath: ofObject: change: context:
中設(shè)置self.searchResultsController.view.hidden = NO
压昼。這個地方有一點需要注意那就是:“在使用KVO的時候可能會造成死循環(huán)”求冷。因為我們監(jiān)聽的是self.searchResultsController.view
的hidden
屬性變化,那么當(dāng)我們在監(jiān)聽的回調(diào)方法中改變這個hidden
屬性又會被監(jiān)聽到然后再調(diào)一次回調(diào)方法.........窍霞。這樣就造成了循環(huán)調(diào)用匠题。為了解決這個問題我們需要在改變hidden
屬性值的地方加上一個判斷如下面的代碼。當(dāng)hidden
等于true
的時候就不在改變hidden
的屬性啦
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (self.searchResultsController.view.hidden && object == self.searchResultsController.view && [keyPath isEqualToString:@"hidden"] && self.searchBar.isFirstResponder )
{
self.searchResultsController.view.hidden = NO;
}
}