UISearchController的使用和自定义UITable

2020-04-29  本文已影响0人  大橘猪猪侠

UISearchController的使用和自定义UITableViewCell

最近由于在工作中需要用到搜索框,于是今天重新弄了一个搜索框的demo,这个demo主要说的就是如何去进行模糊查询数据。

搜索框有很多第三方的库,但是对于一些使用次数不多的,我觉的用系统自带的也不错。

另外顺便说一下如何自定义UITableViewCell和对UITableView的一些样式的设计

首先查询的数据,我这边写的是一个联系人的一些基本信息,用一个person类来描述

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,copy)NSString *tel;
@property(nonatomic,copy)NSString *sex;
@property(nonatomic,copy)NSString *address;
@end

NS_ASSUME_NONNULL_END

然后就是对一些UI的基本设置

代理
<UITableViewDelegate,UITableViewDataSource,UISearchControllerDelegate,UISearchResultsUpdating,DeleteBtnDelegate>
@property(nonatomic,strong)UISearchController *search;
@property(nonatomic,strong)UITableView *tableView;
@property(nonatomic,strong)NSMutableArray *dataList;
@property(nonatomic,strong)NSMutableArray *searchList;


//初始化
self.tableView = [[UITableView alloc]init];
//代理
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    //背景颜色(用于区分单元格之间的间隙)
    self.tableView.backgroundColor = [UIColor colorWithRed:239.0/255.0 green:239.0/255.0 blue:239.0/255.0 alpha:1.0];
    //设置样式
//    self.tableView.separatorStyle = UITableViewCellSelectionStylenon;
    
    //没有数据不显示单元格
    self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];
    
    //搜索框的初始化
    self.search = [[UISearchController alloc]initWithSearchResultsController:nil];
    //代理
    self.search.delegate = self;
    self.search.searchResultsUpdater = self;
    
    //搜索时,背景变模糊
    self.search.obscuresBackgroundDuringPresentation = NO;
    //隐藏导航栏
    self.search.hidesNavigationBarDuringPresentation = YES;
    //位置
    self.search.searchBar.frame = CGRectMake(0, 0, self.search.searchBar.frame.size.width, 44.0);
    
    //添加到tableview的header
    self.tableView.tableHeaderView = self.search.searchBar;
    [self.view addSubview:self.tableView];
    
    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.bottom.left.right.equalTo(self.view);
    }];

因为我们查询数据,都显示在tableView当中,因此,在设置tableview的数量时,需要判断搜索框是否被激活,包括数据显示在单元格当中,也是需要区分搜索框是否激活

- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if(self.search.active){
        return self.searchList.count;
    }else{
        return self.dataList.count;
    }
}

- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    NSString *identifier = @"identifier";
    PersonTableViewCell *cell = [[PersonTableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    if(cell == nil){
        cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    }
    if([cell respondsToSelector:@selector(setSeparatorInset:)]){
        [cell setSeparatorInset:UIEdgeInsetsZero];
    }
    if([cell respondsToSelector:@selector(setLayoutMargins:)]){
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
    cell.delegate = self;
    Person *p = [[Person alloc]init];
    if(self.search.active){
        p = self.searchList[indexPath.row];
        cell.name.text = p.name;
        cell.sex.text = p.sex;
        cell.tel.text = p.tel;
        cell.address.text = p.address;
    }else{
        p = self.dataList[indexPath.row];
        cell.name.text = p.name;
        cell.sex.text = p.sex;
        cell.tel.text = p.tel;
        cell.address.text = p.address;
    }
    
    return cell;
}

重点

对数据进行模糊查询
NSPredicate是用来 过滤获取的数据类,对于一些正则表达式的描述,在这里,我就不详细介绍了。
CONTAINS : 判断字符串内容是否包含搜索的字符串

-(void)updateSearchResultsForSearchController:(UISearchController *)searchController{
    
    NSString *searchString = [self.search.searchBar text];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name CONTAINS %@ OR SELF.sex CONTAINS %@ OR SELF.tel CONTAINS %@ OR SELF.address CONTAINS %@",searchString,searchString,searchString,searchString];
    if(self.searchList!=nil){
        [self.searchList removeAllObjects];
    }
    //过滤数据
    self.searchList = [NSMutableArray arrayWithArray:[self.dataList filteredArrayUsingPredicate:predicate]];
    //刷新表格
    [self.tableView reloadData];
}

模拟器运行结果

Simulator Screen Shot - iPhone SE (2nd generation) - 2020-04-29 at 16.38.54.png Simulator Screen Shot - iPhone SE (2nd generation) - 2020-04-29 at 16.39.26.png

上面两张图是显示的结果。

自定义UITableViewCell

在我们开发中,常常不满足系统的UITableViewCell的格式,因此,我们需要对cell进行自定义

还是按照上面的图片的样式来自定义cell格式

.h文件

#import <UIKit/UIKit.h>

@protocol DeleteBtnDelegate <NSObject>

-(void)deleteMessage:(UITableViewCell *_Nullable)cell;

@end
NS_ASSUME_NONNULL_BEGIN

@interface PersonTableViewCell : UITableViewCell
@property(nonatomic,weak)id<DeleteBtnDelegate>delegate;
@property(nonatomic,strong)UIButton *deleteBtn;
@property(nonatomic,strong)UILabel *name;
@property(nonatomic,strong)UILabel *tel;
@property(nonatomic,strong)UILabel *sex;
@property(nonatomic,strong)UILabel *address;
@end

.m文件
对一些显示的内容初始化,如果你们需要添加其他UI组件,你们可以自行添加,原理都是一样的。

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    if(self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]){
        UILabel *name = [[UILabel alloc]init];
        [self.contentView addSubview:name];
        self.name = name;
        
        UILabel *tel = [[UILabel alloc]init];
        [self.contentView addSubview:tel];
        self.tel = tel;
        
        UILabel *sex = [[UILabel alloc]init];
        [self.contentView addSubview:sex];
        self.sex = sex;
        
        UILabel *address = [[UILabel alloc]init];
        [self.contentView addSubview:address];
        self.address = address;
        
        UIButton *deleteBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [deleteBtn setTitle:@"删除" forState:UIControlStateNormal];
        [deleteBtn addTarget:self action:@selector(deleteMessage:) forControlEvents:UIControlEventTouchUpInside];
        [self.contentView addSubview:deleteBtn];
        self.deleteBtn = deleteBtn;
    }
    return self;;
}

在layoutSubviews对UI组件的位置进行设置
这边我使用的是masnory进行布局,你们也可以用frame来布局,都一样。

-(void)layoutSubviews{
    [super layoutSubviews];
    [self.name mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.equalTo(self).offset(10);
    }];
    [self.sex mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.name).offset(20);
        make.left.equalTo(self).offset(10);
    }];
    [self.tel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.equalTo(self.sex).offset(20);
        make.left.equalTo(self).offset(10);
    }];
    [self.address mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.equalTo(self.tel).offset(20);
        make.left.equalTo(self).offset(10);
    }];
    
    [self.deleteBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self).offset(-10);
        make.top.bottom.equalTo(self);
    }];
}

对cell之间的距离进行设置,
重写-(void)setFrame:(CGRect)frame方法

在自定义cell中,可以用这种方法来设置cell之间的距离,若不自定义,可以对每个数据进行分组,设置每个分组之间的距离也行。

-(void)setFrame:(CGRect)frame{
    //单元格距离左边屏幕的距离
    //frame.origin.x +=10;
    //单元格距离上边屏幕的距离
    //frame.origin.y +=10;
    //单元格下面与下一个单元格之间的距离
    frame.size.height -=10;
    //单元格距离右边屏幕设置的距离
    //frame.size.width -=20;
    [super setFrame:frame];
}

按钮的代理方法的实现

-(void)deleteMessage:(UITableViewCell *_Nullable)cell{
    [self.delegate deleteMessage:self];
}

我也是小白一个,若有错误,请指正!谢谢

上一篇下一篇

猜你喜欢

热点阅读