带有 NSPredicate 的 NSFetchRequest 有时会抛出 NSInvalidArgumentException

发布于 2024-11-10 03:12:00 字数 1956 浏览 5 评论 0原文

这让我感到困惑:

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

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 =='活动')) AND ((LeadID 包含 [cd] 'i')OR (帐号包含[cd] 'i')OR (任何 contactItems.FirstName 包含[cd] 'i')OR (任意 contactItems.LastName 包含[cd] 'i')OR (任何地址项目.Address1 包含[cd] 'i')OR (任意 addressItems.City 包含[cd] 'i'))

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

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

This one is baffling me:

I have a core data set that I search/filter using the following code:

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 is just a NSString.

This works 95% of the time, however every once in a while it catches an NSInvalidArgumentException: Can't use in/contains operator with collection 10076173 (not a collection).

The Predicate String formats to be this:

((isLocalVersion == 1) AND
(LeadStatusID =='Active')) AND
((LeadID contains[cd] 'i')OR
(AccountNumber contains[cd] 'i')OR
(ANY contactItems.FirstName
contains[cd] 'i')OR (ANY
contactItems.LastName contains[cd]
'i')OR (ANY addressItems.Address1
contains[cd] 'i')OR (ANY
addressItems.City contains[cd] 'i'))

My catch allows me to not crash and just return 0 results, but this isn't optimal. Has anyone ever seen this before?

My only clue is that it seems to happen after I modify (and save) a record in the core data (again only sometimes).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

南渊 2024-11-17 03:12:00

是的,您不能将计算结果为集合的表达式作为 fetchRequest 谓词的一部分。 这位于文档中

Core Data 不支持聚合表达式。

Yep, you can't have expressions that evaluate to collections as part of a fetchRequest's predicate. This is in the documentation:

Aggregate expressions are not supported by Core Data.

稚气少女 2024-11-17 03:12:00

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;

The Core Data SQL store supports only one to-many operation per query; therefore in any predicate sent to the SQL store, there may be only one operator (and one instance of that operator) from ALL, ANY, and IN.

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

What might be happening is:

  • if one of the early conditions evaluates to TRUE, the remaining conditions are not evaluated, so no crash occurs
  • if you get to OR (ANY contactItems.FirstName contains[cd] '%@') and it's TRUE, you get your first use of ANY, no crash occurs
  • if you get to OR (ANY contactItems.LastName contains[cd] '%@'), you get your second use of ANY, crash occurs

You need to execute the ANYs separately and combine the results, possibly using NSCompoundPredicate;

趴在窗边数星星i 2024-11-17 03:12:00

LeadID 是否是一个 int 属性?我刚刚遇到了同样的问题,构建了一个谓词,在其中检查一个或多个属性是否包含搜索词。它在大多数情况下都有效,但有时它会失败并出现像您一样的错误。

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

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


作为进一步的证据,我尝试更改谓词以使用 LIKE 而不是 CONTAINS,并且我收到了一个相关的错误,这最终让我知道发生了什么。谓词是

itemNumber LIKE“*test*”或型号LIKE“*test*”或productDescription LIKE“*test*”[..snip..]

,例外情况是

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

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


至于当您使用 CONTAINS 运算符时 Core Data 通常(但并非总是)将 int 属性转换为字符串的原因,我不知道。但我确实知道谓词工作得很好,直到上下文有未保存的更改:特别是当对象的多对多关系属性发生更改时。

Is LeadID a int property by any chance? I just ran into this same problem, constructing a predicate where I check to see if one or more properties contain a search term. It worked most of the time, but every now and then it would fail with an error just like yours.

The problem was that all of the properties I was checking were strings except one. When I removed that property from the predicate, everything worked fine.

I suspect 10076173 is the int value of LeadID for some object in your database. It appears that Core Data will usually convert the int to string like you expect, but sometimes it doesn't and that's when the error happens. The CONTAINS operator doesn't make sense on an integer and it crashes.


As further evidence, I tried changing the predicate to use LIKE instead of CONTAINS and I got a related error which finally tipped me off to what was happening. The predicate was

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

and the exception was

'Can't do regex matching on object 1008.'

At the point I realized 1008 looked familiar... like an itemNumber, which is an Int32.


As for the reason Core Data usually, but not always, converts an int property to a string when you use the CONTAINS operator, I don't know. But I do know that the predicate worked fine until the context had unsaved changes: specifically when an object's to-many relationship property was changed.

凡尘雨 2024-11-17 03:12:00

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

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

Found a similar problem with a predicate that was checking for NSDecimalNumber longitude and part of it came to longitude<-23 and caused an obj_c_exception_throw with no more details. The fix was to ensure that there was a space after the <, i.e. longitude < -23. It basically crashed for anything with <- together, but not >-.

NSPredicate throws some odd undocumented errors.

夜空下最亮的亮点 2024-11-17 03:12:00

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

I seem to remember having a similar problem with collections in Core Data, where my fetch predicate somehow resulted in invalid SQL (other data store types worked fine). It's not an ideal solution, but if you have few enough objects you could do a complete fetch and then filter the result set after the fact.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文