iOS11 UISearchController最佳适配

释放双眼,带上耳机,听听看~!
WYSearchVC.gif

一、背景

想要做一个搜索功能,首先想到了系统的UISearchController但是样式确需要高度的自定义。在适配的过程中发现了好多坑点,尤其是在iOS11上,现在将其总结到下面。

二、做法

修改searchBar的样式

    // 1.设置placeholder
    self.searchVC.searchBar.placeholder = @"Search music/author name.";
    
    // 2.设置searchBar的背景透明
    [self.searchVC.searchBar setBackgroundImage:[UIImage new]];
    self.searchVC.searchBar.searchBarStyle = UISearchBarStyleMinimal;
    
    // 3.设置搜索框文字的偏移
    self.searchVC.searchBar.searchTextPositionAdjustment = UIOffsetMake(3, 0);
    
    // 4.设置搜索框图标的偏移
    CGFloat offsetX = (self.view.bounds.size.width - 200 - 32) / 2;
    [self.searchVC.searchBar setPositionAdjustment:UIOffsetMake(offsetX, 0) forSearchBarIcon:UISearchBarIconSearch];

    // 5.取消按钮和文本框光标颜色
    self.searchVC.searchBar.tintColor = [UIColor blackColor];
    
    // 6.设置搜索文本框背景图片 [圆形的文本框只需要设置一张圆角图片就可以了]
    [self.searchVC.searchBar setSearchFieldBackgroundImage:[UIImage imageWithColor:[UIColor whiteColor] size:CGSizeMake(self.view.bounds.size.width - 32, 36) isRound:YES] forState:UIControlStateNormal];
    // 7.设置搜索按钮图片
    UIImage *searchImg = [[UIImage imageNamed:@"cheez_search_icn"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    [self.searchVC.searchBar setImage:searchImg forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
    // 8.拿到搜索文本框
    UITextField *searchField = [self.searchVC.searchBar valueForKey:@"_searchField"];
    // 9.设置取消按钮文字
    [self.searchVC.searchBar setValue:@"Custom Cancel" forKey:@"_cancelButtonText"];

如果设置了文字和按钮的偏移,需要在UISearchControllerDelegate中在searchVC将要展示和消失的时候做文字按钮偏移处理[在将要展示searchVC的时候取消偏移,在searchVC将要消失的时候设置偏移]

#pragma mark - UISearchControllerDelegate
- (void)willPresentSearchController:(UISearchController *)searchController {
    
    self.view.alpha = 1.0;
    [searchController.searchBar setPositionAdjustment:UIOffsetMake(0, 0) forSearchBarIcon:UISearchBarIconSearch];
}

- (void)willDismissSearchController:(UISearchController *)searchController {
    
    CGFloat offsetX = (self.view.bounds.size.width - 200 - 32) / 2;
    [searchController.searchBar setPositionAdjustment:UIOffsetMake(offsetX, 0) forSearchBarIcon:UISearchBarIconSearch];
}

针对是否是iOS11版本的适配,注意如果在iOS11以下也建议把searchBar用一个view包起来然后添加到控制器中去,不然就有可能出现点击搜索框searchBar不见了等莫名其妙的情况:

    // 2.Install the search bar
    if ([self.navigationItem respondsToSelector:@selector(setSearchController:)]) {
        // 2.1 For iOS 11 and later, wo place the search bar in the navigation bar
        if (@available(iOS 11.0, *)) {
            self.navigationItem.searchController = self.searchVC;
            // 2.2 Set the search bar visible all the time
            self.navigationItem.hidesSearchBarWhenScrolling = NO;
        }

        // 2.3 Hide line view
        __weak typeof(self) weakSelf = self;
        self.observerRef = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {

            NSLog(@"kCFRunLoopBeforeWaiting");
            BOOL targetView = [weakSelf barGroudView:weakSelf.navigationController.view];
            if (targetView) {
                CFRunLoopRemoveObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);
            }
        });
        CFRunLoopAddObserver(CFRunLoopGetMain(), self.observerRef, kCFRunLoopDefaultMode);

    } else {
        UIView *v = [[UIView alloc] initWithFrame:self.searchVC.searchBar.bounds];
        v.frame = CGRectMake(v.frame.origin.x, 64, v.frame.size.width, v.frame.size.height);
        [v addSubview:self.searchVC.searchBar];
        
        [self.view addSubview:v];
    }

完整代码

- (void)prepareSearchVC {
    WYMusicSearchResultVC *resultVC = [WYMusicSearchResultVC new];
    self.searchVC = [[WYCustomSearchVC alloc] initWithSearchResultsController:resultVC];
    [self.searchVC.view addSubview:resultVC.view];
    
    // 1.Use resultVC to update the search results
    self.searchVC.searchResultsUpdater = resultVC;
    
    self.searchVC.searchBar.placeholder = @"Search music/author name.";
    self.searchVC.searchBar.delegate = resultVC;
    self.searchVC.delegate = resultVC;
    
    [self.searchVC.searchBar setBackgroundImage:[UIImage new]];
    self.searchVC.searchBar.searchBarStyle = UISearchBarStyleMinimal;
    self.searchVC.searchBar.searchTextPositionAdjustment = UIOffsetMake(3, 0);
    
    CGFloat offsetX = (self.view.bounds.size.width - 200 - 32) / 2;
    [self.searchVC.searchBar setPositionAdjustment:UIOffsetMake(offsetX, 0) forSearchBarIcon:UISearchBarIconSearch];

    self.searchVC.searchBar.tintColor = [UIColor blackColor]; // 取消按钮和文本框光标颜色
    
    [self.searchVC.searchBar setSearchFieldBackgroundImage:[UIImage imageWithColor:[UIColor whiteColor] size:CGSizeMake(self.view.bounds.size.width - 32, 36) isRound:YES] forState:UIControlStateNormal];
    UIImage *searchImg = [[UIImage imageNamed:@"cheez_search_icn"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    [self.searchVC.searchBar setImage:searchImg forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
    
    [self.searchVC.searchBar sizeToFit];
    
    // 2.Install the search bar
    if ([self.navigationItem respondsToSelector:@selector(setSearchController:)]) {
        // 2.1 For iOS 11 and later, wo place the search bar in the navigation bar
        if (@available(iOS 11.0, *)) {
            self.navigationItem.searchController = self.searchVC;
            // 2.2 Set the search bar visible all the time
            self.navigationItem.hidesSearchBarWhenScrolling = NO;
        }

        // 2.3 Hide line view
        __weak typeof(self) weakSelf = self;
        self.observerRef = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {

            NSLog(@"kCFRunLoopBeforeWaiting");
            BOOL targetView = [weakSelf barGroudView:weakSelf.navigationController.view];
            if (targetView) {
                CFRunLoopRemoveObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);
            }
        });
        CFRunLoopAddObserver(CFRunLoopGetMain(), self.observerRef, kCFRunLoopDefaultMode);

    } else {
        UIView *v = [[UIView alloc] initWithFrame:self.searchVC.searchBar.bounds];
        v.frame = CGRectMake(v.frame.origin.x, 64, v.frame.size.width, v.frame.size.height);
        [v addSubview:self.searchVC.searchBar];
        
        [self.view addSubview:v];
    }
    
    // 3.It is usually good to set the presentation context
    self.definesPresentationContext = YES;
    
    UITextField *searchField = [self.searchVC.searchBar valueForKey:@"_searchField"];
    searchField.font = [UIFont systemFontOfSize:14];
}

- (BOOL)barGroudView:(UIView *)targetView {
    for (UIView *sView in targetView.subviews) {
        if ([sView isKindOfClass:NSClassFromString(@"_UINavigationControllerPaletteClippingView")]) {
            if (sView.subviews.count > 0 && sView.subviews[0].subviews.count > 0 && sView.subviews[0].subviews[0].subviews.count > 1) {
                sView.subviews[0].subviews[0].subviews[1].hidden = YES;
                return YES;
            }
        }
    }
    
    return NO;
}

三、iOS11后UITbaleView刷新单行跳动解决方案

tableView.estimatedRowHeight = 0;
tableView.estimatedSectionFooterHeight = 0;
tableView.estimatedSectionHeaderHeight = 0;

demo:https://github.com/wangyansnow/WYSearchVC

 

人已赞赏
iOS文章

计时器的简单实现(GCD)

2019-10-26 17:55:12

iOS文章

iOS之事件的传递和响应机制

2019-10-27 18:39:33

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索