美文网首页
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