【问题标题】:NSFetchRequest with NSPredicate sometimes throws NSInvalidArgumentException带有 NSPredicate 的 NSFetchRequest 有时会抛出 NSInvalidArgumentException
【发布时间】:2011-05-26 20:18:40
【问题描述】:

这个让我很困惑:

我有一个核心数据集,我使用以下代码搜索/过滤:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Lead" inManagedObjectContext:moc]];
NSString *predicateString = [NSString stringWithFormat:@"("
                       "(isLocalVersion == %@) AND (LeadStatusID =='Active')"
                       ") AND ("
                       "(LeadID contains[cd] '%@')"
                       "OR (AccountNumber contains[cd] '%@')"
                       "OR (ANY contactItems.FirstName contains[cd] '%@')"
                       "OR (ANY contactItems.LastName contains[cd] '%@')"
                       "OR (ANY addressItems.Address1 contains[cd] '%@')"
                       "OR (ANY addressItems.City contains[cd] '%@')"
                       ")", [NSNumber numberWithBool:YES], sTerm, sTerm, sTerm, sTerm, sTerm, sTerm];

NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
[fetchRequest setPredicate:predicate];

NSError *error = nil;
NSArray *leads = nil;
@try {
    leads = [moc executeFetchRequest:fetchRequest error:&error];
}
@catch (NSException *exception) {
    LogSevere(@"Error Executing Fetch Request: %@", exception);
    leads = [NSArray array];
}
@finally {
    [fetchRequest release];
}

sTerm 只是一个NSString

这在 95% 的情况下都有效,但每隔一段时间它就会捕获一个 NSInvalidArgumentException: Can't use in/contains operator with collection 10076173 (not a collection).

谓词字符串格式如下:

((isLocalVersion == 1) AND (LeadStatusID =='活动'))和 ((LeadID 包含 [cd] 'i')或 (帐号包含 [cd] 'i')或 (任何contactItems.FirstName 包含[cd] 'i')OR (ANY contactItems.LastName 包含[cd] 'i') 或(任何 addressItems.Address1 包含[cd] 'i')OR (ANY addressItems.City 包含[cd] 'i'))

我的捕获允许我不会崩溃并且只返回 0 个结果,但这不是最佳的。有没有人见过这个?

我唯一的线索是,它似乎发生在我修改(并保存)核心数据中的记录之后(同样只是有时)。

【问题讨论】:

    标签: objective-c core-data nspredicate nsfetchrequest


    【解决方案1】:

    是的,您不能将评估为集合的表达式作为 fetchRequest 谓词的一部分。 This is in the documentation:

    Core Data 不支持聚合表达式。

    【讨论】:

    • 好的,那么在这种情况下,我应该得到isLocalVersionLeadStatusID 的结果集,然后单独评估每个剩余的表达式并组合结果?
    • 谢谢。单独执行 OR 并组合结果似乎是有效的。
    • 但我在这里看不到任何聚合表达式。你能指出哪些部分是聚合表达式吗?谢谢。
    【解决方案2】:

    Core Data SQL 存储每个查询仅支持一对多操作;因此,在发送到 SQL 存储的任何谓词中,可能只有一个来自 ALLANYIN 的运算符(以及该运算符的一个实例)。

    https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html

    可能发生的事情是:

    • 如果早期条件之一评估为 TRUE,则不会评估其余条件,因此不会发生崩溃
    • 如果您到达OR (ANY contactItems.FirstName contains[cd] '%@') 并且它是TRUE,您将首次使用ANY,不会发生崩溃
    • 如果您访问OR (ANY contactItems.LastName contains[cd] '%@'),您将获得第二次使用ANY发生崩溃

    您需要单独执行 ANY 并组合结果,可能使用 NSCompoundPredicate

    【讨论】:

      【解决方案3】:

      LeadID 是否是 int 属性?我刚刚遇到了同样的问题,构建了一个谓词,我在其中检查一个或多个属性是否包含搜索词。它大部分时间都能正常工作,但时不时会出现像你一样的错误。

      问题是我检查的所有属性都是字符串,除了一个。当我从谓词中删除该属性时,一切正常。

      我怀疑 10076173 是您数据库中某个对象的 LeadID 的 int 值。 Core Data 似乎通常会像您期望的那样将 int 转换为字符串,但有时它不会,这就是错误发生的时候。 CONTAINS 运算符对整数没有意义,它会崩溃。


      作为进一步的证据,我尝试将谓词更改为使用 LIKE 而不是 CONTAINS,我得到了一个相关的错误,最终让我知道正在发生的事情。谓词是

      itemNumber LIKE "*test*" OR model LIKE "*test*" OR productDescription LIKE "*test*" [..snip..]

      例外是

      '无法对对象 1008 进行正则表达式匹配。'

      当时我意识到 1008 看起来很熟悉......就像一个 itemNumber,它是一个 Int32。


      至于 Core Data 通常但不总是在使用 CONTAINS 运算符时将 int 属性转换为字符串的原因,我不知道。但我确实知道,在上下文未保存更改之前,谓词工作正常:特别是当对象的多对多关系属性发生更改时。

      【讨论】:

      • 哇,非常有用的信息。我将不得不进一步调查。我使用了一个 cludge 来解决这个问题,但可能会用这个信息重新调查它。 +1
      【解决方案4】:

      在检查 NSDecimalNumber 经度的谓词中发现了一个类似的问题,其中一部分到达 longitude<-23 并导致 obj_c_exception_throw 没有更多详细信息。修复是确保< 之后有一个空格,即longitude < -23。它基本上与<- 一起崩溃,但不是>-

      NSPredicate 抛出一些奇怪的未记录错误。

      【讨论】:

        【解决方案5】:

        我似乎记得在 Core Data 中的集合也有类似的问题,我的 fetch 谓词不知何故导致 SQL 无效(其他数据存储类型工作正常)。这不是一个理想的解决方案,但如果您有足够少的对象,您可以进行完整的提取,然后在事后过滤结果集。

        【讨论】:

          猜你喜欢
          • 2014-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-16
          • 2013-11-12
          • 2012-04-05
          • 1970-01-01
          相关资源
          最近更新 更多