领域cocoa:通过PKfind多个对象

很久以前的潜伏者,第一次提问。

我在一个项目中使用了Realm Cocoa(来自Realm.io),并且正在努力通过PK进行search。 比方说,我有一个名为RLMFoo的实体,它有一个名为bar的主键。 我也有一个PK列表,比方说存储在一个数组中:

NSArray *primaryKeys = @[@"bar1", @"bar2", @"bar3"]

有没有什么办法在一个查询中从我的领域检索RLMFoo类的所有实体?

我已经尝试了迄今为止:

  1. 格式为: [RLMFoo objectsInRealm:realm withPredicate:[NSPredicate predicateWithFormat:@"bar IN %@", primaryKeys]];
  2. Realm's where: [RLMFoo objectsInRealm:realm where:@"bar IN %@", strippedIds];
  3. 谓词与块:

 NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { RLMFoo *foo = (RLMFoo *)evaluatedObject; return [primaryKeys containsObject:foo.bar]; }]; [RLMFoo objectsInRealm:realm withPredicate:predicate]; 

但是到目前为止我发现的唯一工作是查询每个主键值的领域并汇总结果,这看起来很慢:

 NSMutableArray *results = [NSMutableArray new]; for (NSString *primaryKey in primaryKeys) { RLMFoo *obj = [RLMFoo objectInRealm:realm forPrimaryKey:primaryKey]; if (obj) { [results addObject:obj]; } } 

有谁知道有更好的方法来做到这一点?

=========解释为什么前三种方法不起作用=======

1)这个不起作用的原因从exception消息中看起来很明显:IN只有2个值,尽pipeIN的SQL版本应该尽可能的多。 从RLMQueryUtil.mm的源代码可以看出,BETWEEN运算符也是如此:

  if (compp.predicateOperatorType == NSBetweenPredicateOperatorType || compp.predicateOperatorType == NSInPredicateOperatorType) { // Inserting an array via %@ gives NSConstantValueExpressionType, but // including it directly gives NSAggregateExpressionType if (exp1Type != NSKeyPathExpressionType || (exp2Type != NSAggregateExpressionType && exp2Type != NSConstantValueExpressionType)) { @throw RLMPredicateException(@"Invalid predicate", @"Predicate with %s operator must compare a KeyPath with an aggregate with two values", compp.predicateOperatorType == NSBetweenPredicateOperatorType ? "BETWEEN" : "IN"); } 

这是堆栈跟踪:

 *** Terminating app due to uncaught exception 'Invalid predicate', reason: 'Predicate with IN operator must compare a KeyPath with an aggregate with two values' *** First throw call stack: ( 0 CoreFoundation 0x03334946 __exceptionPreprocess + 182 1 libobjc.A.dylib 0x0292aa97 objc_exception_throw + 44 2 <redacted> 0x00190569 _ZN12_GLOBAL__N_127update_query_with_predicateEP11NSPredicateP9RLMSchemaP15RLMObjectSchemaRN7tightdb5QueryE + 2553 3 <redacted> 0x0018f7ea _Z27RLMUpdateQueryWithPredicatePN7tightdb5QueryEP11NSPredicateP9RLMSchemaP15RLMObjectSchema + 378 4 <redacted> 0x0018b23c _Z13RLMGetObjectsP8RLMRealmP8NSStringP11NSPredicate + 748 5 <redacted> 0x0017d721 +[RLMObject objectsInRealm:withPredicate:] + 161 

2)这在理性和堆栈轨迹上非常相似:

 *** Terminating app due to uncaught exception 'Invalid predicate', reason: 'Predicate with IN operator must compare a KeyPath with an aggregate with two values' *** First throw call stack: ( 0 CoreFoundation 0x03328946 __exceptionPreprocess + 182 1 libobjc.A.dylib 0x0291ea97 objc_exception_throw + 44 2 <redacted> 0x00184599 _ZN12_GLOBAL__N_127update_query_with_predicateEP11NSPredicateP9RLMSchemaP15RLMObjectSchemaRN7tightdb5QueryE + 2553 3 <redacted> 0x0018381a _Z27RLMUpdateQueryWithPredicatePN7tightdb5QueryEP11NSPredicateP9RLMSchemaP15RLMObjectSchema + 378 4 <redacted> 0x0017f26c _Z13RLMGetObjectsP8RLMRealmP8NSStringP11NSPredicate + 748 5 <redacted> 0x00171751 +[RLMObject objectsInRealm:withPredicate:] + 161 6 <redacted> 0x00171465 +[RLMObject objectsInRealm:where:args:] + 213 7 <redacted> 0x001712f3 +[RLMObject objectsInRealm:where:] + 419 

3)这个又是非常相似的。 归结起来,NSPredicate的完整function集缺乏对领域的支持。

 *** Terminating app due to uncaught exception 'Invalid predicate', reason: 'Only support compound and comparison predicates' *** First throw call stack: ( 0 CoreFoundation 0x03308946 __exceptionPreprocess + 182 1 libobjc.A.dylib 0x028fea97 objc_exception_throw + 44 2 <redacted> 0x001638bd _ZN12_GLOBAL__N_127update_query_with_predicateEP11NSPredicateP9RLMSchemaP15RLMObjectSchemaRN7tightdb5QueryE + 4397 3 <redacted> 0x0016240a _Z27RLMUpdateQueryWithPredicatePN7tightdb5QueryEP11NSPredicateP9RLMSchemaP15RLMObjectSchema + 378 4 <redacted> 0x0015de5c _Z13RLMGetObjectsP8RLMRealmP8NSStringP11NSPredicate + 748 5 <redacted> 0x00150341 +[RLMObject objectsInRealm:withPredicate:] + 161 

你的前两个选项应该没有问题。 编写这个查询最简单的方法是:

 NSArray *primaryKeys = @[@"bar1", @"bar2", @"bar3"] RLMResults *results = [RLMFoo objectsWhere:@"id IN %@", primaryKeys]; 

一个名为objectsWithPredicate的方法也可以工作。 你可以分享更多的代码/堆栈跟踪时使用你的第一个几个方法? 我认为其他地方也有问题

在你的帮助下,我find了这个行为的原因。 我真正的代码更接近:

  NSArray *primaryKeys = @[ @"bar1", @"bar2", @"bar3" ]; NSString *primaryKeyName = @"bar"; RLMResults *results = [RLMFoo objectsInRealm:self.realm withPredicate:[NSPredicate predicateWithFormat:@"%@ IN %@", primaryKeyName, primaryKeys]]; 

这是一个方法,PK和PK名称是方法调用的参数。 从理论上讲,这将允许我的类检索任何PK名称的对象。 原来我的错误是假设predicateWithFormat在这种情况下,将以类似于stringWithFormat的方式工作,并正确地将PK名称replace为第一个参数,并将PKarrays作为第二个参数。 然而,解决scheme竟然是先组装格式string,然后是谓词:

  RLMResults *results = [RLMFoo objectsInRealm:self.realm withPredicate:[NSPredicate predicateWithFormat: [NSString stringWithFormat:@"%@ IN %%@", primaryKeyName], primaryKeys]]; 

谢谢Yoshyosh你的时间。