iOS - UISearchController搜索框与NSPredicate谓词

2023-05-16

一、UISearchController

搜索框的用处很大,就不用废话了,在iOS8以前是用UISearchBar加代理实现的。
现在已经废弃,鼓励使用新的UISearchController
首先遵守UISearchResultsUpdating协议

@interface RootTableViewController ()<UISearchResultsUpdating>  
//再实现必须的方法
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController

//搜索代理方法,搜索框获得第一响应或内容变化时触发  
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController  
{  
   NSLog(@激活了搜索框");  
}

再创建UISearchController,因为很多方法都要对搜索框进行判断,写成一个属性

@property (nonatomic,retain)UISearchController *searchC;  

//初始化UISearchController,把搜索框添加在tableView的headerView上
//添加搜索栏  
_searchC = [[UISearchController alloc]initWithSearchResultsController:nil];  
//设置frame  
_searchC.searchBar.frame = CGRectMake(0, 0, 414, 50);  

//更新代理  
_searchC.searchResultsUpdater = self;  

//搜索结果不变灰  
_searchC.dimsBackgroundDuringPresentation = NO;  

//添加到header  
self.tableView.tableHeaderView = _searchC.searchBar;

这样运行就能看到搜索框了,点击也会打印文字。

二、NSPredicate谓词

光有搜索框没什么卵用,还要有搜索功能,内部的功能就需要谓词来实现了
谓词的功能很强大,同时它还可以使用正则表达式,可以实现各种邮箱验证,手机号验证,以及各种查找功能。
使用的方法

1.创建谓词
NSPredicate *testPredicate = [NSPredicate predicateWithFormat:@"age < 50"];

谓词的语法也很全面:
Format后面可以跟很多:
(1)比较运算符>,<,==,>=,<=,!=可用于数值及字符串例:@"number > 100"
(2)范围运算符:IN、BETWEEN例:@"number BETWEEN {1,5}" @"address IN {'shanghai','beijing'}"
(3)字符串本身:SELF 例:@“SELF == ‘APPLE’"
(4)字符串相关:

BEGINSWITH、ENDSWITH、CONTAINS例:@"name CONTAIN[cd] 'ang'" //包含某个字符串
@"name BEGINSWITH[c] 'sh'" //以某个字符串开头
@"name ENDSWITH[d] 'ang'" //以某个字符串结束
注:[c]不区分大小写[d]不区分发音符号即没有重音符号[cd]既不区分大小写,也不区分发音符号。

(5)通配符:LIKE例:@"name LIKE[cd] 'er'" //代表通配符,Like也接受[cd]. @"name LIKE[cd] '???er'"

(6)正则表达式:MATCHES例:NSString *regex = @"^A.+e$"; //以A开头,e结尾 @"name MATCHES %@",regex
用正则表达式简单匹配一个邮箱

    /* 
   正则表达式常用的  
    ^ ---  匹配输入字符串的开始位置 
    $ ---  匹配输入字符串的结束位置 
    * --- 匹配前面的子表达式任意次 
     + --- 匹配前面的子表达式一次或多次 
     ? --- 匹配前面的子表达式零次或一次 
     .点 --- 匹配除“\r\n”之外的任何单个字符 
     \d --- 匹配一个数字字符。等价于[0-9] 
    \D --- 匹配一个非数字字符。等价于[^0-9]\w --- 等价于[A-Za-z_0-9]\转义 

     */  

    //匹配一个邮箱地址  
    //结构 (字母数字)@(字母数字)(.)(字母2~4个)  
    NSString *emailRegex = @"\\w+@\\w+\\.[A-Za-z]{2,4}";  

    NSPredicate *emailPredicate = [NSPredicate predicateWithFormat:@"name MATCHES %@",emailRegex];
2.进行过滤,有两种方法,

一种是对数组进行过滤,把符合谓词条件的对象产生一个新的数组
一种是单独判断一个对象是否满足谓词条件,返回值为BOOL

 //过滤产生新的数组  
    self.searchArray =  [NSMutableArray arrayWithArray:[_dataArray filteredArrayUsingPredicate:testPredicate]];  

//对单个对象依次判断  
  if ([testPredicate evaluateWithObject:personDic])   
  {  
         //添加到搜索数组当中去  
         [_searchArray addObject:personDic];  
   }

这里要注意一点,数组内放的对象可以是一个字典,也可以是一个类。

最后给出我写的完整的tableView上搜索框的使用

//  RootTableViewController.m      
#import "RootTableViewController.h"  
#import "Person.h"  

@interface RootTableViewController ()<UISearchResultsUpdating>  

@property (nonatomic,retain)NSMutableArray *dataArray;//全部数据数组  
@property (nonatomic,retain)NSMutableArray *searchArray;//搜索结果数组  

@property (nonatomic,retain)UISearchController *searchC;//搜索框  

@end  

@implementation RootTableViewController  
//懒加载  
-(NSMutableArray *)dataArray  
{  
    if (!_dataArray) {  
        _dataArray = [[NSMutableArray alloc]init];  
    }  
    return _dataArray;  
}  
-(NSMutableArray *)searchArray  
{  
    if (!_searchArray) {  
        _searchArray = [[NSMutableArray alloc]init];  
    }  
    return _searchArray;  
}  

- (void)viewDidLoad {  
    [super viewDidLoad];        
    self.navigationItem.title = @"search";  

    //添加搜索栏  
    _searchC = [[UISearchController alloc]initWithSearchResultsController:nil];        
    _searchC.searchBar.frame = CGRectMake(0, 0, 414, 50);  

    //更新代理  
    _searchC.searchResultsUpdater = self;  

    //搜索结果不变灰  
    _searchC.dimsBackgroundDuringPresentation = NO;  

    //便利初始化创建数据  

    NSArray *nameArray = [NSArray arrayWithObjects:@"王",@"李型剂",@"王青云",@"张菲菲",@"abe",@"ABe",@"aBS",@"wang@12.com", @"wan@126.cn",nil];  

    int ageList[] = {12,43,56,123,34,44,21,22,11};  
    for (int i = 0; i < 9; i++) {  
        Person *person = [Person personWithName:nameArray[i] Age:(NSInteger)ageList[i]];  

        //把全部人存到数组当中去  
        [self.dataArray addObject:person];  
    }  

    //添加到header  
    self.tableView.tableHeaderView = _searchC.searchBar;  

    //注册单元格  
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"CELL"];        
}    
//搜索代理方法,搜索框获得第一响应或内容变化时触发  
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController  
{  
    //得到搜索框的文字  
    NSString* str = searchController.searchBar.text;  
    NSLog(@"%@",str);  
    //创建个谓词  
    // < > >= <= !=  
    NSPredicate *testPredicate = [NSPredicate predicateWithFormat:@"age < 50"];  

    //IN BETWEEN  
    NSPredicate *testPredicate_2 = [NSPredicate predicateWithFormat:@"age BETWEEN {50,100}"];  
    NSPredicate *testPredicate_3 = [NSPredicate predicateWithFormat:@"name IN{'王','张菲菲'}"];  

    //testPredicate  
//    @"name CONTAINS[cd] 'ang'"   //包含某个字符串  
//    @"name BEGINSWITH[c] 'sh'"     //以某个字符串开头  
//    @"name ENDSWITH[d] 'ang'"      //以某个字符串结束  
    NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"name CONTAINS %@",str];  

    //[c]不区分大小写 [d]无音调  [cd]两个都不要  
     NSPredicate *namePredicate_2 = [NSPredicate predicateWithFormat:@"name CONTAINS[c] %@ ",str];  

    //正则表达式      
    //匹配一个邮箱地址  
    //结构 (字母数字)@(字母数字)(.)(字母2~4个)  
    NSString *emailRegex = @"\\w+@\\w+\\.[A-Za-z]{2,4}";  

    NSPredicate *emailPredicate = [NSPredicate predicateWithFormat:@"name MATCHES %@",emailRegex];  

    //清空搜索数组  
    [_searchArray removeAllObjects];  

    //过滤,这里可以换不同的谓词进行试验  
    self.searchArray =  [NSMutableArray arrayWithArray:[_dataArray filteredArrayUsingPredicate:namePredicate_2]];  

    for (Person *person in _searchArray) {  
        NSLog(@"%@,%ld",person.name,person.age);  
    }        
    //刷新tableView  
    [self.tableView reloadData];  

}  


#pragma mark - Table view data source  

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {  
#warning Incomplete implementation, return the number of sections  
    return 1;  
}  

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {  
#warning Incomplete implementation, return the number of rows  

    //如果搜索框激活  
    if (_searchC.active) {  
        return _searchArray.count;  
    }  
    return _dataArray.count;  
}  

//cell的填充  
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {  
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL" forIndexPath:indexPath];  

    Person *onePerson = _dataArray[indexPath.row];  

    //如果搜索框激活  
    if (_searchC.active) {  
        onePerson = _searchArray[indexPath.row];  
    }  

    cell.textLabel.text = [NSString stringWithFormat:@"姓名:    %@, ----- 年龄:    %ld",onePerson.name,onePerson.age];  

    return cell;  
}    
@end

person类
Person.h

#import <Foundation/Foundation.h>  

@interface Person : NSObject  

@property (nonatomic,retain)NSString *name;//姓名  
@property (nonatomic,assign)NSInteger age;//年龄  

//init  
-(instancetype)initWithName:(NSString*)name Age:(NSInteger)age;  

//便利  
+(instancetype)personWithName:(NSString*)name Age:(NSInteger)age;  

@end

Person.m

#import "Person.h"  

@implementation Person  
//重写初始化方法  
-(instancetype)initWithName:(NSString *)name Age:(NSInteger)age  
{  
    self = [super init];  
    if (self) {  
        _age = age;  
        _name = name;  
    }  
    return self;  
}  

//便利构造器  
 +(instancetype)personWithName:(NSString *)name Age:(NSInteger)age  
{  
    Person *person = [[Person alloc]initWithName:name Age:age];  
    return person;  
}    
@end



文/简单也好(简书作者)
原文链接:http://www.jianshu.com/p/95e9c8660198
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS - UISearchController搜索框与NSPredicate谓词 的相关文章

  • TestFlight 提供反馈按钮

    我正在使用 iOS 8 的最新 testflight 版本 我将自己添加为内部测试人员 现在当我使用 testflight 打开应用程序时 我找不到反馈按钮 如果有人有任何线索 请告诉我 您在 Testflight 应用程序中提供反馈 打开
  • 如何使用 iOS 可达性

    我正在开发一个使用网络的 iPhone 应用程序 iPhone 通过 HTTP 请求与我的服务器通信 并且应该可以在 WiFi 和 3G 上运行 我目前使用NSURLConnection initWithRequest向我的服务器发送异步请
  • 如何以编程方式设置设备(UI)方向?

    希望屏幕 UI 上的所有内容都能够从横向左向右旋转 反之亦然 我该怎么做呢 这是私人的吗 我知道 BOOL shouldAutorotateToInterfaceOrientation UIInterfaceOrientation inte
  • 如何检测 UISwipeGestureRecognizer 的结束?

    来自苹果文档 滑动是一种离散手势 因此每个手势仅发送一次关联的操作消息 void touchesEnded NSSet touches withEvent UIEvent event 当我使用 UISwipeGestureRecognize
  • Cordova 2.4.0 或 2.5.0 或 2.6.0 和 requirejs

    Cordova 2 4 0 及更高版本支持 AMD 加载到 javascript 中 我特别希望将 Cordova 2 5 0 与最新版本的 RequireJS backbone jquery jquery mobile 一起使用 我还没有
  • 如何开始复杂级别的跨平台移动应用开发? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Swift SpriteKit edgeLoopF​​romRect 问题

    下面的代码可以识别底部和顶部边缘场景和球按预期弹开 但是 那左边缘和右边缘现场的情况一直被破坏 如果施加足够的力 球会离开屏幕 然后最终返回 就好像场景的边缘超出了 iPhone 模拟器窗口的边缘 import SpriteKit clas
  • 如何从 SDK 实现每个会话的 Google Places 自动完成功能?

    是否可以从 Android 和 iOS 应用程序的 place sdk 实现基于会话的自动完成 根据 6 月 11 日生效的新 Google 地图框架定价 对自动完成的请求可以分为基于击键 会话的请求 我找不到描述实施步骤的文档 除了这个参
  • 错误域=kAFAssistantErrorDomain 代码=209“(空)”

    我面临着一个问题SFSpeechRecognizer 启动应用程序几秒钟后 我开始收到错误消息 错误域 kAFAssistantErrorDomain 代码 209 空 和 错误 域 kAFAssistantErrorDomain 代码 2
  • ios swift parse:从 3 个类收集数据

    我有这样的结构 User CardSet 带有指向 User objectId 的指针 user 和 col name 带有点 cards 的卡片到 Card Set objectId 和列 name 我想选择所有卡数据 包括当前用户的卡集
  • dyld:无法加载插入的库

    当我尝试运行 UI 和单元测试时 出现异常 dyld 无法加载插入的库 private var containers Bundle Application AutoTestingApp app Frameworks IDEBundleInj
  • iOS:生成pdf时绘制文本时如何设置字体?

    我在ios应用程序中使用drawpdf函数生成pdf 同时调用nsobject类中的drawtext函数 它根据我指定的框架和字符串清楚地绘制文本 我的代码是 void drawText NSString textToDraw inFram
  • 为什么 iOS 启动屏幕很慢?

    我的 iOS 应用程序启动屏幕大约需要 3 5 秒 我有一张将在启动屏幕后加载的地图 我的用户必须等待启动屏幕加载 然后再等待 3 秒才能加载地图 有没有办法最大限度地减少启动屏幕时间 基本上这种延迟意味着you在启动过程中做了一些非常错误
  • 在 iPhone 3GS 与 iPhone 4 上为 Mobile Safari 嵌入 HTML5 视频

    我在服务器上的 mp4 文件中有 H 264 AAC 编码的视频 mime 类型的视频 mp4 添加到 Web 服务器 IIS 7 并且我有一个带有视频标签的页面
  • iOS 7 上 Safari 浏览器的用户代理

    我只想在带有 Safari 浏览器的 iPhone 和 iPod 中打开我的网站 对于 Chrome Dolphin 等任何其他浏览器 它不应该打开 但目前我从几乎所有设备获得相同的用户代理 对于Safari User Agent Stri
  • 如何向标准 UIButton 添加徽章? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 是否可以在标准中添加看起来标准的徽章UIButton 如果不支持半原生 那么实现此目的最简单的方法是什么 示例图片 这是 Sascha
  • Objective-C 中发送给对象的消息可以被监听或者打印出来吗? [复制]

    这个问题在这里已经有答案了 可能的重复 Objective C 中拦截方法调用 https stackoverflow com questions 1618474 intercept method call in objective c 如
  • 使用 MapKit 的地形和卫星视图

    我是 Mapkit View 的新手 当我给出没有目的地的纬度和经度时 我想显示 MapKit中是否可以通过地形 卫星视图来显示地图 有教程链接吗 我看过一些访问 Google 地图 API html 文件 的示例 有必要吗 或者您可以通过
  • 如何在 UICollectionView 中将行居中?

    我有一个UICollectionView与随机细胞 有什么方法可以让我将行居中吗 默认情况下它是这样的 x x x x x x x x x x x x x x 这是所需的布局 x x x x x x x x x x x x 我必须做这样的事
  • CoreBluetooth:检测设备超出范围/连接超时

    我正在设计一个 iOS 框架来处理多个 BLE 设备 均为同一类型 目前一切都运行良好 除了一件事 客户想要一个包含可用设备的列表 但是 我如何检测过去发现的设备何时不再可用 当我尝试连接到不再可用的设备时 会出现另一个问题 文档说 连接尝

随机推荐