【问题标题】:Does CoreData on iPhone support IN predicates?iPhone 上的 CoreData 是否支持 IN 谓词?
【发布时间】:2010-11-28 23:49:31
【问题描述】:

我正在尝试根据用户定义的类型列表获取一堆特定类型的记录……

[fetchRequest setEntity:[NSEntityDescription entityForName:@"myRecord" inManagedObjectContext:self.managedObjectContext]];  
NSSet   *shipTypes = [NSSet setWithObjects:[NSNumber numberWithInt:70],
                    [NSNumber numberWithInt:71],
                    [NSNumber numberWithInt:72],
                    [NSNumber numberWithInt:73],
                    [NSNumber numberWithInt:74],
                     nil];
NSPredicate *aPredicate = [NSPredicate predicateWithFormat:@"type in %@", shipTypes];
[fetchRequest setPredicate:aPredicate];
theRecords = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

…运行时,executeFetchRequest 消息抛出异常…

 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'unimplemented SQL generation for predicate : (type IN {71, 73, 70, 72, 74})'

是我做错了什么,还是真的不支持?

【问题讨论】:

  • 这应该可行,但我终其一生都无法弄清楚为什么不可行。阅读 Predicate Format String Syntax 文档,看看你是否能找到任何东西:developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…
  • 同意。您可以尝试使用 NSArray 而不是 NSSet,但这应该可以正常工作。
  • 如果你成功了,你应该将其中一个答案标记为正确。

标签: iphone sqlite core-data


【解决方案1】:

我相信 Alex 是正确的,你必须使用 NSArray,但显然如果在这里接受 NSSet 会更好,因为顺序并不那么重要(尽管它可能会影响 SQL 的运行速度)。

作为旁注,我从来没有在任何代码中使用 +predicateWithFormat: 调用,因为它不能进行编译时健全性或类型检查。我强烈建议使用单独的类。

在这种情况下,我会这样做:

fetchRequest.entity = [NSEntityDescription entityForName:@"myRecord" inManagedObjectContext:self.managedObjectContext]];

NSArray *shipTypes = [NSArray arrayWithObjects:[NSNumber numberWithInt:70],
                                        [NSNumber numberWithInt:71],
                                        [NSNumber numberWithInt:72],
                                        [NSNumber numberWithInt:73],
                                        [NSNumber numberWithInt:74],
                                         nil];
fetchRequest.predicate = [NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"type"] rightExpression:[NSExpression expressionForConstantValue:shipTypes] modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0];

theRecords = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

并不是说这会在编译时捕捉到这个特定的错误,但它可能会在 NSExpression 级别捕捉到它,从而更清楚出了什么问题。

【讨论】:

  • 它使用 NSArray 而不是 NSSet 工作。感谢大家抓住这个。
【解决方案2】:

尝试将您的谓词更改为@"ANY type IN %@"

【讨论】:

    【解决方案3】:

    嗯。我尝试添加 ANY 关键字和使用 NSArray。实际上,当我从 Core Data 得到这个异常时,我开始使用 NSAArray。回想起来,因为我将两个表达式与 AND 结合起来,这对 Core Data 来说是个问题。 (我知道我应该回去验证一下,但是我在阅读这篇文章时突然想到了这个想法。)这是我的原始表达:

    NSPredicate* predicate = [NSPredicate predicateWithFormat:@"BPM BETWEEN { %d, %d } AND GENRE IN %@", lower, upper, genres];
    

    我的解决方案是将其分成两部分。现在,我使用谓词发出 BPM 查询,但我获取结果数组并将 -filteredArrayUsingPredicate 与 @"genre IN %@" 一起使用。因此:

    array = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"genre IN %@", genres]];
    

    这对我有用。

    【讨论】:

      【解决方案4】:

      我为此苦苦挣扎。最终我为每个集合做了一个子谓词。

      例如:

      NSMutableArray *subpredicates = [NSMutableArray array];
      
      NSArray *shipTypes = [NSArray arrayWithObjects:[NSNumber numberWithInt:70],
                                          [NSNumber numberWithInt:71],
                                          [NSNumber numberWithInt:72],
                                          [NSNumber numberWithInt:73],
                                          [NSNumber numberWithInt:74],
                                           nil];
      
      for (NSNumber *num in shipTypes) {
          [subpredicates addObject:[NSPredicate predicateWithFormat:@"ANY type == %@", num]];         
      }
      
      NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
      

      假设类型是 NSSet。如果不是,您可以:

      for (NSNumber *num in shipTypes) {
          [subpredicates addObject:[NSPredicate predicateWithFormat:@"type == %@", num]];         
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-05
        • 2016-01-26
        • 2020-07-24
        • 1970-01-01
        • 1970-01-01
        • 2021-10-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多