【问题标题】:Predicate works for array but not for fetchRequest谓词适用于数组但不适用于 fetchRequest
【发布时间】:2011-03-06 00:46:08
【问题描述】:

我正在尝试创建一个 fetchRequest,它向我显示尚未在另一个数组中的所有值。此代码返回我期望的数组:

NSArray *questionChoices = [self.currentQuestionChoiceGroup.questionChoices allObjects]; 
NSArray *filteredQuestionChoices  = [questionChoices filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NONE %@ == code", myarr]];

myarr 包含 1 项,并且该 1 项按预期从过滤结果中排除。但是,此代码不起作用:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"QuestionChoice" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:@"NONE %@ == code AND questionChoiceGroup == %@", myarr, self.currentQuestionChoiceGroup];

当我执行这个获取请求时,我得到了属于当前 questionChoiceGroup 的所有 questionChoices,包括在 myarr.xml 中有代码的问题。它似乎完全忽略了 AND 语句的第一部分。

我看不出两者之间有什么区别会导致不同的结果。有人可以帮忙吗?

EDIT 更简单的解释:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"questionChoiceGroup == %@ AND NONE %@ == code", self.currentQuestionChoiceGroup, [NSArray arrayWithObject:@"A"]];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"displayOrder" ascending:YES]];
request.entity = [NSEntityDescription entityForName:@"QuestionChoice" inManagedObjectContext:self.managedObjectContext];

request.predicate = predicate;
NSArray *filteredQuestionChoices1 = [self.managedObjectContext executeFetchRequest:request error:nil];
NSLog(@"my filtered question choices 1: %@", [filteredQuestionChoices1 valueForKey:@"code"]);   

NSArray *filteredQuestionChoices2  = [filteredQuestionChoices1 filteredArrayUsingPredicate:predicate];
NSLog(@"my filtered question choices 2: %@", [filteredQuestionChoices2 valueForKey:@"code"]);

filteredQuestionChoices1 包含一个代码为“A”的项目。 filtersQuestionChoices2 没有该项目。第二个谓词如何过滤掉第一个谓词没有过滤掉的任何东西?两个语句都使用完全相同的谓词。如果我在数组上使用谓词,如果完全相同的谓词将过滤掉这些对象,为什么我要从 fetchedRequest 中取回对象?

【问题讨论】:

    标签: objective-c ios nspredicate nsfetchrequest


    【解决方案1】:

    我会尝试修改您的谓词。而不是:

    [NSPredicate predicateWithFormat:@"NONE %@ == code", myarr]
    

    试试:

    [NSPredicate predicateWithFormat:@"NOT(code IN %@)", myarr]
    

    我认为后者可能更容易让 CoreData 转换为相应的 SQL 条件。

    【讨论】:

    • 实际上,这正是我最终所做的。 NOT code IN 工作得很好。但是,如果核心数据有时可以以不同于数组的方式处理谓词,那么显然我对核心数据有些不理解。我试图理解这一点以避免将来出现问题。另外,最好知道NONENOT IN 是否完全相同。
    【解决方案2】:

    查看核心数据指南中的Fetch Predicates and Sort Descriptors

    如果您使用的是基于 SQL 的数据存储(例如,SQLite),那么谓词将被转换为 SQL 并由数据库调用,而不是由 Cocoa 调用。因此,您可以获得与标准数组不同的行为,并且对支持的内容也有限制。具体来说,ALLANYIN 操作存在限制(您的 NONE 操作符相当于 NOT( ANY ... ))。

    看起来您正在尝试对作为参数提供的数组执行NONE 操作,而不是从数据库中提取的数据数组。我敢打赌,这就是 SQL 翻译的谓词遇到问题的地方。

    【讨论】:

      【解决方案3】:

      当使用AND 的语句有两个部分时,将每个部分括在括号中。此外,在与动态属性名称进行比较时,%K 是适当的格式说明符。

      request.predicate = [NSPredicate predicateWithFormat:@"(NONE %K == code) AND (questionChoiceGroup == %@"), myarr, self.currentQuestionChoiceGroup];
      

      Apple 的谓词编程指南中的一个示例:

      Cocoa 支持多种类型 谓词,包括以下内容:

      • 简单的比较,例如等级 == 7 或名字,如“Mark”

      • 案例或 变音符号不敏感查找,例如 名称包含[cd] '雪铁龙'

      • 逻辑 操作,例如(firstName 以'M'开头)和(姓氏如 'Adderley')

      【讨论】:

      • 刚刚试过了;它不会改变任何东西......虽然它确实使代码更清晰。
      • 使用 %K 作为动态属性名称的格式说明符。我已经更新了我的示例。
      • 我不是在比较动态属性名称...NONE %@ == code 旨在消除所有在 %@ 传入的数组中具有代码的项目...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-02
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多