ios - 境界 cocoa : finding multiple objects by PKs

标签 ios objective-c realm

长期潜伏者,第一次提问。

我在一个项目中使用 Realm Cocoa(来自 Realm.io),并且很难通过 PK 执行搜索。 假设我有一个名为 RLMFoo 的实体,它有一个名为 bar 的主键。我还有一个 PK 列表,假设存储在一个数组中:

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

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

到目前为止我已经尝试过:

  1. 谓词格式:[RLMFoo objectsInRealm:realm withPredicate:[NSPredicate predicateWithFormat:@"bar IN %@", primaryKeys]];
  2. Realm 的位置:[RLMFoo objectsInRealm:realm where:@"bar IN %@", strippedIds];
  3. 带 block 的谓词:

.

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) 从异常消息中可以看出这不起作用的原因:IN 仅采用 2 个值,尽管 IN 的 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) 这个也非常相似。归根结底, Realm 缺乏对 NSPredicate 完整功能集的支持。

*** 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 的方法也可以。在使用前几种方法时,您可以分享更多代码/堆栈跟踪吗?我认为其他地方发生了问题

关于ios - 境界 cocoa : finding multiple objects by PKs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27798898/

相关文章:

realm - Xcode 10.2 swift 5 : dynamic' property '' must also be '@objc'

java - Realm :记录顺序已更改

ios - 如何访问 MKMapItem 的类别或类型

ios - CoreLocation CLLocationManagerDelegate 在飞行途中返回缓存/延迟的位置

objective-c - 将 "SELF IN"与 NSPredicate 和 RLMResults 一起使用

ios - 链接器命令失败,退出代码为 1

ios - 在 Unity 中为原生 IOS 应用程序提供 subview

ios - 柯南错误 :I need to cross build packages for os:iOS with my Macos, 但是当第一个包完成时,它在测试时破坏了我的 cpt

ios - 从linux命令行编译IOS程序

iphone - 为什么 Xcode 的自动完成总是认为我的属性是 int?