简介

nspredicate提供了一个通用的数据查询方式,有两种Predicate类型,分别是comparison 和 compound:

  • comparison predicate 使用运算符来比较两个表达式
  • compound predicate 对比两个或多个predicate的结果,或者让其他的predicate 失效.

Cocoa 里支持非常多的 predicate 类型,例如:

  • 简单的比较: grade == 7 或者 firstName like 'Mark'
  • 大小写或读音敏感的查询:name contains[cd] 'citroen'
  • 逻辑操作符:(firstName beginswith 'M') AND (lastName like 'Adderley')

你还可以根据关系创建predicate,例如:group.name matches 'work.*'ALL children.age > 12以及ANY children.age > 12根据操作创建例如:@sum.items.price < 1000.

你可以把 predicates 用在任何类上,但这个类必须是遵循 key-value-coding 的类。

nspredicate的局限

predicate查询可能会翻译成sql语句或xml格式或者其他格式,这取决于后端存储的类型。因此并不是所有的操作后端存储都能支持。下面是一些例子:

  • matches 关键字使用正则来进行匹配,所以是不被CoreData的 sql 存储支持的,但是却可以用在内存中的过滤。
  • CoreData sql 存储里每次查询只能支持一对多的操作,因此任何应用在sql存储的predicate都只能有 ALL AND IN 中的一个操作符。
  • 不能将任意的SQL查询转换成predicate。
  • ANYKEY操作符只能用在SpotLight的查询中。
  • SpotLight中不支持关系查询。

创建Predicate

  1. 使用格式化的字符串创建

    可以使用nspredicate的类方法predicateWithFormat 从字符串创建一个predicate对象:

    nspredicate* predicate = [nspredicate predicateWithFormat: @"(lastName like[cd] %@) AND (birthday > %@)",lastNameSearchString,birthdaySearchDate];

    示例代码中的like[cd]操作符表示大小写(c 表示case-insensitive,)发音(d 表示 diacritic-insensitive)不敏感。

  2. 字符串常量、变量和通配符

    字符串常量必须用引号包裹起来,用单引号或双引号都是可以的,如果你用%@来进行参数替换(例如firstName like %@),引号会自动添加,如果你用的是字符串常量,那你必须自己用引号包裹起来:

    nspredicate* predicate = [nspredicate predicateWithFormat: @"lastName like[c] 'S*'"];
    // 或者
    nspredicate* predicate = [nspredicate predicateWithFormat: @"lastName like[c] \"S*\""];

    在使用通配符时必须考虑引号的问题,你应该把通配符添加到一个预定义的变量中来进行参数替换:

    Nsstring* prefix = @"prefix";
    Nsstring* suffix = @"suffix";
    nspredicate* predicate = [nspredicate predicateWithFormat: @"SELF like[c] %@",[[prefix stringByAppendingString: @"*"] stringByAppendingString: suffix]];
    BOOL ok = [predicate evaluateWithObject: @"prefixxxxxxxsuffix"];

    下面则是一个错误的例子:

    predicate = [nspredicate predicateWithFormat: @"SELF like[c] %@*%@",prefix,suffix];
    ok = [predicate evaluateWithFormat: @"prefixxxxxsuffix"];
  3. 布尔值

    用下面的方法可以来测试布尔值是否相等:

    let aBool = true
    
    let anotherPredicate = nspredicate(format: "anAttribute == %@",NSNumber(bool: aBool))
    nspredicate(format: "anAttribute == YES")
  4. 动态属性名

    当通过参数替换时,因为string变量会被双引号包裹,所以不能用%@来指定动态属性:

    Nsstring* attribute = @"firstName";
    Nsstring* attributeValue = @"Adam";
    nspredicate* predicate = [nspredicate predicateWithFormat: @"%@ like %@",attributeName,attributeValue];

    如果需要指定一个动态属性,可以使用%K:

    predicate = [nspredicate predicateWithFormat: @"%K like %@",attributeValue];
  5. 直接用代码来创建的nspredicate

    Objective-C:

    NSExpression *lhs = [NSExpression expressionForKeyPath:@"revenue"]; NSExpression *greaterThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:1000000]]; nspredicate *greaterThanPredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:greaterThanRhs modifier:NSDirectPredicateModifier type:NSGreaterThanorEqualToPredicateOperatorType options:0]; NSExpression *lessthanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:100000000]]; nspredicate *lessthanPredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:lessthanRhs modifier:NSDirectPredicateModifier type:NSLessthanPredicateOperatorType options:0]; NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates: @[greaterThanPredicate,lessthanPredicate]];

    Swift:

    let lhs = NSExpression(forKeyPath: "revenue")
    
    let greaterThanRhs = NSExpression(forConstantValue: "张三")
    let greaterPredicate = NSComparisonPredicate(leftExpression: lhs,rightExpression: greaterThanRhs,modifier: .DirectPredicateModifier,type: .BeginsWithPredicateOperatorType,options: .CaseInsensitivePredicateOption)
    
    let lessthanRhs = NSExpression(forConstantValue: 1000000000000)
    let lessthanPredicate = NSComparisonPredicate(leftExpression: lhs,rightExpression: lessthanRhs,type: .LessthanorEqualToPredicateOperatorType,options: .CaseInsensitivePredicateOption)
    
    let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [greaterPredicate,lessthanPredicate])
  6. 使用模板来创建predicate

    Objective-C:

    nspredicate* predicateTemplate = [nspredicate predicateWithFormat: @"lastName like[c] $LAST_NAME"];
    nspredicate* predicate = [predicateTemplate predicateWithSubstitutionVariables: [NSDictionary dictionaryWithObject:@"Turner" forKey:@"LAST_NAME"]];

    Swift:

    let predicateTemplate = nspredicate(format: "lastName like[c] $LAST_NAME")
    
    let new = predicateTemplate.predicateWithSubstitutionVariables(["LAST_NAME":"turner"])
  7. 使用Predicate

    使用nspredicate的evaluateWithObject方法并传入要查询的数据,这个方法会返回一个布尔值:

    Objective-C:

    nspredicate* predicate = [nspredicate predicateWithFormat: @"SELF in %@",@[@"Stig",@"Shaffig",@"Chris"]];
    BOOL result = [predicate evaluateWithObject: @"Shaffig"];

    Swift:

    let predicate = nspredicate(format: "SELF in %@",["Stig","Shaffig","Chris"]) // SELF IN {"Stig","Chris"}
    let result = predicate.evaluateWithObject("Stig") // true

    在数组中使用Predicate

    Objective-C:

    NSMutableArray* array = [NSMutableArray arrayWithObjects: @"Nick",@"Ben",@"Adam",@"Melissa",nil];
    
    nspredicate* sPredicate - [nspredicate predicateWithFormat: @"SELF contains[c] 'e'"];
    [array filterUsingPredicate: sPredicate];

    在predicate中传入key-path

    Nsstring* departmentName = ...;
    nspredicate* predicate = [nspredicate predicateWithFormat: @"department.name like %@",departmentName];

    如果你使用的是一对多的关系,那么predicate的构造会有些许不同:

    nspredicate* predicate = [nspredicate predicateWithFormat: @"ANY employees.firtName like 'Matthew'"];
    nspredicate* predicate = [nspredicate predicateWithFormat: @"ANY employees.salary > %f",salary];

    使用空值

    comparison predicate不会匹配任何的null值,除非nil或者NSNull,也就是($value == nil)。看一下下面的例子:

    Nsstring* firstName = @"Ben";
    
           NSArray* array = @[@{@"lastName" : @"Turner"},@{@"firstName" : @"Ben",@"lastName" : @"Ballard",@"birthday" : [NSDate dateWithString: @"1972-03-24 10:45:32 +0600"]}
                              ];
           nspredicate* predicate = [nspredicate predicateWithFormat:@"firstName like %@",firstName];
           NSArray* filteredArray = [array filteredArrayUsingPredicate:predicate];
           NSLog(@"%@",filteredArray);

    predicate 匹配了包含firstName 键的值,却没匹配上不包含这个键的值,下面的例子是同样的道理:

    NSDate* referenceDate = [NSDate dateWithTimeIntervalSince1970:0];
           predicate = [nspredicate predicateWithFormat:@"birthday > %@",referenceDate];
           filteredArray = [array filteredArrayUsingPredicate:predicate];
           NSLog(@"%@",filteredArray); // (
           // { birthday = "1972-03-24 04:45:32 +0000";
            // firstName = Ben;
            //lastName = Ballard; })

    如果你想要匹配null值,你就得添加一条额外的对比:

    predicate = [nspredicate predicateWithFormat:@"(firstName == %@) || (firstName == nil)"];
           filteredArray = [array filteredArrayUsingPredicate:predicate];
           NSLog(@"%@",filteredArray);

    在 CoreData 上使用predicate

    下面的例子展示了在CoreData中使用nspredicate进行查询:

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
           NSEntityDescription *entity = [[NSEntityDescription entityForName: @"Employee"] inManagedobjectContext: managedobjectContext];
           [request setEntity: entity];
           NSNumber *salaryLimit = @2000;
           nspredicate *predicate = [nspredicate predicateWithFormat:@"salary > %@",salaryLimit];
           [request setPredicate: predicate];
           NSError *error;
           NSArray *array = [managedobjectContext executeFetchRequest: request error: &error];

在Swift中使用NSPredicate进行数据库查询的更多相关文章

  1. ios – 为什么“NOT IN”在这个NSPredicate中不起作用?

    A.b和B.a与许多关系相反.为什么这个谓词为A工作:虽然这个没有:我认为两个谓词都应该给出相同的结果–通过b与bObject无关的As的集合.但实际上,第一个给出正确的集合,而第二个没有.更新:这是sampleproject,其中A.b由Account.filtered_clients体现,B.a由Client.filtered_by体现.在MasterViewController.m中切

  2. ios – 如何创建一个比较对象所有属性的谓词?

    例如,我有一个具有三个属性的对象:firstName,middleName,lastName.如果我想使用nspredicate在所有属性中搜索字符串“john”.而不是像以下那样创建谓词:[nspredicatepredicateWithFormat:@“(firstName包含[cd]%@)OR(lastName包含[cd]%@)OR(middleName包含[cd]%@)”,@“john”,

  3. ios – 使用NSPredicate搜索/过滤自定义类数组

    我有一个包含自定义类对象的数组,我想基于其中一个类属性是否包含自定义字符串来过滤数组.我有一个方法,传递我想要搜索的属性(列)和它将搜索的字符串(searchString).这是我的代码:但是,它始终抛出异常displayProviders=[[tempfilteredArrayUsingPredicate:query]mutablecopy];说这个类不是密钥值编码兼容的密钥[无论searchS

  4. ios – 构建复杂的NSCompoundPredicate最好的方法是什么?

    我需要用许多数据构建一个nspredicate.例如在sql中,我会做如下的操作:我正在努力与如何构建一个用于核心数据的nspredicate.我已经阅读了只提供简单实例的文档.如果有人能指出一个更复杂的例子,我一定会感激的.那么我在这里回答了两年,很多人觉得有帮助.我的帖子已被删除.以下是更新的解决方案URL.https://www.radeeccles.com/convert-sql-stat

  5. ios – 如何通过在CloudKit中的creationDate进行查询?

    我想从CloudKit获取最后十分钟的公共/私人条目.我尝试了一些这样的效果,但失败了:但这会让我得到数据,但是我不知道我是查询一切,还是只是某种上限:我想能够查询一定的时间.这样做可能没有在客户端做创建排序逻辑吗?

  6. iOS:NSPredicate使用NSDate进行比较

    解决方法我认为你今天的看法有问题.AFAIK,NSDate代表了一个绝对的时间点,所以你在没有“时间”的情况下创建“日期”的努力似乎是徒劳的.而且使用NSDateFormatter设置日期也是不稳定的.我想你必须创建两个不同的NSDate对象:startOfCurrentDay和endOfCurrentDay,并且亲自地使用NSCalendar.如果这样做,您的提取请求谓词将是:

  7. 如何在IOS中使用两个谓词过滤UITableView

    解决方法是的,像这样…然后,这将显示所有以名字从搜索开始的人,或者姓氏以搜索开始.我更喜欢使用这种格式在单个谓词中使用OR和AND,因为它使整个代码更易读.这也可以用来获得谓词的NOT.如果您使用单个谓词内置复合谓词,也可以很容易地感到困惑.

  8. ios – 具有多重条件的NSPredicate

    我正在尝试创建具有多个条件的nspredicate.我找到了几个解决方案,但是他们似乎都没有使用我的方法.我找到的最好的一个是下面.这是我的单一谓词方法,它的工作原理很好:这是我的编辑版本与多个条件.我不知道出了什么问题.有任何想法吗?解决方法你可以试试这个

  9. ios – 如何在Swift中为PHFetchOptions格式化NSPredicate?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  10. ios – 在NSArray上NSPredicate来搜索任何对象

    我有一个数组的名称,地址,电话的对象.诺斯等我想能够搜索阵列中任何一个术语的出现–无论是在名称字段,地址字段等中.我有这样的想法:这导致异常“不能在/包含运算符与集合中使用”.UPDATE.我现在可以搜索最多三个字段.当我添加第四个,我得到这个异常:“无法解析格式字符串…”谓词代码现在是:谓词搜索字段有三个限制吗?如何解决这个问题?

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部