分析系统搜索框UISearchController

更新搜索的内容

在UISearchControllerDelegate代理方法updateSearchResultsForSearchController中通过以下的代码来实现搜索的数据更新:

- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
   NSString *searchText = searchController.searchBar.text;
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SELF CONTAINS %@)", searchText];
    filterArr = searchText.length>0?[dataArr filteredArrayUsingPredicate:predicate]:dataArr; //当搜索内容清空后也有内容
    [self.tableView reloadData];
}

结果展示控制器问题

        EOCSearchResultViewCtrl *resultSearchCtrl = [[EOCSearchResultViewCtrl alloc] init];
        _searchCtrl = [[UISearchController alloc] initWithSearchResultsController:resultSearchCtrl];

在初始化UISearchController的时候initWithSearchResultsController如果设置为自己的话,设置成nil就好,不要设置成self,当设置为nil的时候也就是说搜索的结果,会在self中进行展示,当然一般是在self中用tableview进行展示。如果设置为别的控制器,就会展示在别的控制器中,其实也就只是相当于拆分开来罢了。

searchBar的问题

    [self.view addSubview:self.tableView];
    [self.tableView setTableHeaderView:self.searchCtrl.searchBar];

我们将searchBar设置为tableView的头视图,并且当点击搜索框的时候,在UISearchControllerDelegate代理的willPresentSearchController方法和didPresentSearchController方法分别打断点可得以下结果:


以上是打断点过后的图


分析系统搜索框UISearchController_第1张图片

以上是点击搜索框之前的图

分析系统搜索框UISearchController_第2张图片

以上是点击搜索框之后的图

从上可以知道当点击了searchBar过后,系统将searchBar取出来移到了导航栏上面,而不再是tableView的头视图,而且点击之前和之后的searchBar是同一个,查看他们的内存地址可以知道。

另外需要注意的点

  • 当使用搜索框的时候最好不要将self.automaticallyAdjustsScrollViewInsets设置为NO,因为会很难调坐标,会出现64px的问题。
  • searchBar添加在scrollView以及它的子类上,而不是添加在view上
  • searchController必须设置成成员变量,否则只会是添加了一个view上去,而其代理方法那些都不会响应,因为你不设置成成员变量,出了那个方法,你就被释放掉了
  • definesPresentationContext 当SearchResultsController不为nil,即搜索结果在别的控制器展示的时候,需要将definesPresentationContext设置为YES,即表示当UISearchController控制器present到需要展示的目标控制器的时候,可以覆盖当前的控制器,否则当跳到目标控制器时,上面会有一段空白


    分析系统搜索框UISearchController_第3张图片

修改搜索框的一些设置

    //修改背景色
    self.searchCtrl.searchBar.barTintColor = [UIColor yellowColor];
    //修改光标和取消文字颜色
    self.searchCtrl.searchBar.tintColor = [UIColor orangeColor];
    //修改图标
    [self.searchCtrl.searchBar setImage:[UIImage imageNamed:@"voice_gray"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
    [self.searchCtrl.searchBar setImage:[UIImage imageNamed:@"message_gray"] forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
    [self.searchCtrl.searchBar setImage:[UIImage imageNamed:@"message_gray"] forSearchBarIcon:UISearchBarIconClear state:UIControlStateHighlighted];
    // KVC 修改textfield的文字
    UITextField *textField = [self.searchCtrl.searchBar valueForKey:@"_searchField"];
    textField.textColor = [UIColor orangeColor];
    textField.font = [UIFont systemFontOfSize:12.f];
    // KVC 修改textfield的默认提示文字   两级就用keyPath
    [textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
    // KVC 修改searchBar的取消按钮文字   两级就用keyPath
    [self.searchCtrl.searchBar setValue:@"取消" forKey:@"_cancelButtonText"];

/* 下面是三期的内容 */

    // 一、 修改searchBar  颜色,光标,cancel文字颜色
    
    self.searchCtrl.searchBar.barTintColor = [UIColor redColor];
    self.searchCtrl.searchBar.tintColor = [UIColor purpleColor];  // 修改光标,cancel文字颜色
    
    // 二、 修改cancel文字
    
    // 1. 必须cancelButton出现的时候,才可以修改,这样子不是我们想要的,体验效果差,使用的话,也要和_searchCtrl.searchBar.showsCancelButton = YES;结合使用
    
    UIButton *cancelBtn = [self.searchCtrl.searchBar valueForKey:@"_cancelButton"];
    [cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
    
    // 2. 遍历找到button,它也会陷入和第一种方式一样的弊端:必须cancelButton出现的时候,才可以修改
    
    // 3. 挺好的,推荐使用,但是需要注意,当你有navigationController的时候,你可能会全局修改UIBarButtonItem,通过这个方法:[[UIBarButtonItem appearance] setTitleTextAttributes,这样子导致bug
    [[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitle:@"取消"];
    
    
    // 三、 修改textField,变成半圆角;加一个边界
    
    // 1. 第一种用kvc
    UITextField *searchTextField = [self.searchCtrl.searchBar valueForKey:@"_searchField"];
    searchTextField.layer.cornerRadius = 14.f;
    searchTextField.layer.masksToBounds = YES;
    searchTextField.layer.borderWidth = 2.f;
    searchTextField.layer.borderColor = [UIColor brownColor].CGColor;
    searchTextField.tintColor = [UIColor blackColor];
    
    // 2. 第二种遍历
    
    // 如果有上下两条边线就去掉上下两条边线,遍历就可以了
    for (UIView *view in self.searchCtrl.searchBar.subviews) {
        
        if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
            [view removeFromSuperview];
        }
    }



上面是使用KVC来进行修改,也可以通过遍历的方法来进行修改,但是进行搜索过后,进入SearchResultsController后就回到了原状。

iOS11的改变

iOS11 搜索框做了很多改变,我们一般这么用:

    if (@available(iOS 11, *)) {
        
        self.navigationItem.searchController = self.searchCtrl;
        self.navigationItem.hidesSearchBarWhenScrolling = NO;
        [self.searchCtrl.searchBar setPositionAdjustment:UIOffsetMake(100, 0) forSearchBarIcon:UISearchBarIconSearch];
        
    } else {
        
        self.tabelView.tableHeaderView = self.searchCtrl.searchBar;
        
    }

半定制搜索框

没有实现当点击搜索框的时候,会跳到导航条,但是可以改变textfield的大小,用系统的改变不了。自定义搜索框需要自定义UISearchController和UISearchBar。代码如下:
EOCClassSearchCtl:

#import 
#import "EOCClassSearchBar.h"

@protocol EOCClassSearchCtrlDelegate 
- (void)didStartSearching;
- (void)didTapSearchBtn;
- (void)didTapCancelBtn;
- (void)didChangeSearchText:(NSString *)text;
@end

@interface EOCClassSearchCtl : UISearchController
@property(nonatomic, strong)EOCClassSearchBar *classSearchBar;
@property(nonatomic, weak)id  classSearchCtrlDelegate;
@end
#import "EOCClassSearchCtl.h"

@interface EOCClassSearchCtl ()
@end

@implementation EOCClassSearchCtl

- (instancetype)initWithSearchResultsController:(UIViewController *)searchResultsController {
    
    if (self = [super initWithSearchResultsController:searchResultsController]) {
    }
    return self;
}

#pragma mark - UISearchBar delegate method
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    //代理传递方法
    if (_classSearchCtrlDelegate) {
        [searchBar becomeFirstResponder];
        [_classSearchCtrlDelegate didStartSearching];
    }
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    
    if (_classSearchCtrlDelegate) {
        [searchBar resignFirstResponder];
        [_classSearchCtrlDelegate didTapCancelBtn];
    }
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    
    if (_classSearchCtrlDelegate) {
        [_classSearchCtrlDelegate didChangeSearchText:searchText];
    }
}


#pragma mark - getter method
- (EOCClassSearchBar *)classSearchBar {
    
    if (!_classSearchBar) {
        _classSearchBar = [[EOCClassSearchBar alloc] initWithFrame:CGRectMake(0.f, 0.f, self.view.eoc_width, 44.f)];
        _classSearchBar.delegate = self;
    }
    return _classSearchBar;
}

@end

EOCClassSearchBar:
.h里面没有什么东西,.m文件如下:

#import "EOCClassSearchBar.h"

@interface EOCClassSearchBar ()

@property(nonatomic, strong)UITextField *searchTextField;
@property(nonatomic, strong)UIButton *cancelBtn;
@property(nonatomic, strong)UIImageView *searchBarImageView;

@end

@implementation EOCClassSearchBar


- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        // 截取手势事件,避免当修改textfield的frame后,点击最左边的区域,也响应了事件
        UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];
        [self addGestureRecognizer:tapGesture];
    }
    return self;
}


- (void)tapAction
{
    NSLog(@"%s", __func__);
}
//修改textfield的frame只能在layoutSubviews中
- (void)layoutSubviews {
    [super layoutSubviews];
    // 修改textfield的frame
    self.searchTextField.frame = ({
        CGRect frame = self.searchTextField.frame;
        frame.origin.x = 60.f;
        frame.size.width -= 60.f;
        frame;
    });
}
// 绘制搜索框
- (void)drawRect:(CGRect)rect {
    self.barTintColor = [UIColor orangeColor];
    self.tintColor = [UIColor redColor];
    
    self.showsCancelButton = YES;
    //    self.barTintColor = EOCColor(240, 243, 245);
    [self becomeFirstResponder];
    
    UITextField *textField = self.searchTextField;
    textField.placeholder = @"Search EightClock";
    textField.font = [UIFont systemFontOfSize:12.f];
    textField.backgroundColor = EOCColor(240, 243, 245);
    textField.textColor = [UIColor greenColor];
    textField.textAlignment = NSTextAlignmentLeft;
    
    [self.cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
    [self.cancelBtn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
    
    //在搜索框的底部画一条绿线  画线条
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0.f, self.frame.size.height)];
    [path addLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height)];
    
    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
    shapeLayer.path = path.CGPath;
    shapeLayer.strokeColor = [UIColor greenColor].CGColor;
    shapeLayer.lineWidth = 2.5f;
    [self.layer addSublayer:shapeLayer];
    
}

- (void)btnAction:(UIButton *)btn {
    
    self.searchTextField.text = @"";
    // 调用代理,清空搜索内容
    [self.delegate searchBar:self textDidChange:@""];
    
}

#pragma mark - getter method
- (UITextField *)searchTextField {
    
    if (!_searchTextField) {
        for (id view in [[self.subviews lastObject ]subviews]) {
            if ([view isKindOfClass:NSClassFromString(@"UISearchBarTextField")]) {
                _searchTextField = (UITextField *)view;
            }
        }
    }
    
    return _searchTextField;
}

- (UIButton *)cancelBtn {
    
    if (!_cancelBtn) {
        for (id view in [[self.subviews lastObject ]subviews]) {
            if ([view isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
                _cancelBtn = (UIButton *)view;
            }
        }
    }
    
    return _cancelBtn;
}

- (UIImageView *)searchBarImageView {
    if (!_searchBarImageView) {
        for (id view in [[self.subviews lastObject ]subviews]) {
            if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
                _searchBarImageView = (UIImageView *)view;
//                _searchBarImageView.userInteractionEnabled = YES;
            }
        }
    }
    return _searchBarImageView;
}
@end

你可能感兴趣的:(分析系统搜索框UISearchController)