美文网首页
ios 对UISearchController的封装使所有的回

ios 对UISearchController的封装使所有的回

作者: __Simon__ | 来源:发表于2017-07-28 17:09 被阅读51次

在之前的一片文章UISearchController中介绍了UISearchController的使用,可以看到其中涉及到很多的委托,在使用UISearchController的时候需要导入相关的协议,设置代理,然后实现协议中的方法。每次都这样写还是比较麻烦的。所以可以对UISearchController做一次封装。将遵循协议、设置代理、实现方法这套流程放在UISearchController的子类中来实现,子类对外暴露一组Block属性。这样代理方法的要实现的功能就可以通过Block来完成啦。

YBSearchController.h文件

#import <UIKit/UIKit.h>

@interface YBSearchController : UISearchController

/**
 设置是否一直显示搜索结果页面
 */
@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导致崩溃,目前没有找到更好的解决办法所以使用@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];
    }
}

// 监听 self.searchController.searchResultsController.view 的hidden属性,让搜索结果页面一直显示
- (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

注意点

  • YBSearchControllerUISearchController的子类。所以使用方法与UISearchController的使用方法一样,只是在需要使用UISearchController的代理方法的时候改成了我们封装的Block属性来实现。

  • 在上面的YBSearchController.m方法中我们可以看到为了让搜索结果页面searchResultsController一直显示我们使用到了KVO技术。来监听searchResultsController.viewhidden属性并在监听的回调方法observeValueForKeyPath: ofObject: change: context:中设置self.searchResultsController.view.hidden = NO。这个地方有一点需要注意那就是:“在使用KVO的时候可能会造成死循环”。因为我们监听的是self.searchResultsController.viewhidden属性变化,那么当我们在监听的回调方法中改变这个hidden属性又会被监听到然后再调一次回调方法.........。这样就造成了循环调用。为了解决这个问题我们需要在改变hidden属性值的地方加上一个判断如下面的代码。当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;
    }
}

相关文章

网友评论

      本文标题:ios 对UISearchController的封装使所有的回

      本文链接:https://www.haomeiwen.com/subject/eavxlxtx.html