使用聚合操作崩溃:“ALL"在 Core Data iOS 应用程序中 [英] Crash using Aggregate Operation: "ALL" in a Core Data iOS Application

查看:24
本文介绍了使用聚合操作崩溃:“ALL"在 Core Data iOS 应用程序中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 iphone 应用程序,我使用 Group 和 Contact 对象建立了一个简单的多对多关系.一个群组可以有多个联系人,联系人可以属于多个群组.

I'm working on an iphone application and I have a simple many-to-many relationship set up with Group and Contact objects. A group can have many contacts and contacts can belong to multiple groups.

我正在尝试使用以下谓词选择特定联系人尚未属于的所有组.(注:uid 字段是我用来唯一标识联系人实体的字符串字段)

I'm trying to select all groups that a particular contact does NOT already belong to using the following predicate. (Note: the uid field is a string field that I used to uniquely identify contact entities)

[NSPredicate predicateWithFormat:@"ALL contacts.uid != %@", contactUId]

根据 Apple 的谓词编程指南,ALL 聚合操作是有效的,但我收到以下异常,表明这是一个不受支持的谓词:

According to Apple's Predicate Programming Guide, the ALL aggregate operation is valid but I get the following exception indicating that this is an unsupported predicate:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported predicate (null)'

我可以使用类似的谓词来选择联系人已经属于的所有组,使用此谓词,这样看来我已经正确定义了所有关系和字段.

I can use a similar predicate to select all groups that a contact does already belong to using this predicate so it appears that I have all of the relationships and fields defined properly.

[NSPredicate predicateWithFormat:@"ANY contacts.uid == %@", contactUId]

异常是在构造谓词时抛出的,而不是在我尝试实际执行获取请求时抛出,因此它似乎与我使用的语法而不是核心数据支持有关.我做错了什么?

The exception is thrown when constructing the predicate and not when I'm trying to actually execute the fetch request so it seems to be related to the syntax I'm using rather than Core Data support. What am I doing wrong?

推荐答案

核心数据编程指南说

获取和存储类型之间存在一些交互作用.在 XML、二进制和内存存储中,谓词和排序描述符的评估是在 Objective-C 中执行的,可以访问 Cocoa 的所有功能,包括 NSString 上的比较方法.另一方面,SQL 存储将谓词和排序描述符编译为 SQL,并在数据库本身中评估结果.

There are some interactions between fetching and the type of store. In the XML, binary, and in-memory stores, evaluation of the predicate and sort descriptors is performed in Objective-C with access to all Cocoa's functionality, including the comparison methods on NSString. The SQL store, on the other hand, compiles the predicate and sort descriptors to SQL and evaluates the result in the database itself.

它继续描述了使用 NSPredicate 和 NSSQLiteStoreType 的一些其他限制,但您在此处使用ALL"是一个(未记录的)限制,与获取请求如何发出 SQL 相关.

It goes on to describe some other limitations on the use of NSPredicate with NSSQLiteStoreType, but your use of "ALL" here is an (undocumented) limitation that has to do with how the fetch request emits SQL.

在幕后,CoreData 为您的架构生成三个表:

Under the hood, CoreData generates three tables for your schema:

  • 联系人表格
  • 组表
  • 将它们关联起来的连接表

因此,当您调用 myGroup.contacts 时,会运行以下内容:

And so when you call myGroup.contacts, something like this gets run:

select * from Group join JOIN_TABLE on Group.pk == JOIN_TABLE.group_pk join Contact on JOIN_TABLE.contact_pk == Contact.pk where Group.pk == 12

一个点字符背后有很多事情要做!

There's a lot going on behind one dot character!

无论如何,要真正满足您的查询,您需要这样的东西.我在实际的 SQLite CD 数据库上对此进行了测试,因此表名看起来很奇怪,但应该仍然可以理解:

Anyway, to actually fulfill your query, you'd need something like this. I tested this on an actual SQLite CD database, so the table names look strange, but it should still be comprehensible:

select ZGROUP.Z_PK as outer_pk from ZGROUP where "myUID" not in 
(select ZCONTACT.ZUID as contact_uid from ZGROUP join Z_1GROUPS on Z_1GROUPS.Z_2GROUPS == ZGROUP.Z_PK join ZCONTACT on Z_1GROUPS.Z_1CONTACTS == ZCONTACT.Z_PK where ZGROUP.Z_PK == outer_pk)

我不是 SQL 专家,但我的观察首先是这个查询会很慢,其次它与我们开始使用的 NSPredicate 相去甚远.因此,只有通过大量的努力,CD 才能针对您想要执行的操作提出 SQL 查询,并且它提出的查询不会比在 ObjC 中的简单实现好多少.

I'm no SQL expert, but my observations are first of all that this query is going to be slow, and second of all that it is kind of a long ways from the NSPredicate that we started with. So it would be only through a great deal of effort that CD could up with an SQL query for what you want to do, and the query that it would come up with would not be much better than a naive implementation in ObjC.

无论值多少钱,Apple 开发人员都会在这里说

For whatever it's worth, an Apple developer says here that ALL is unsupported in SQLite and the documentation to the contrary is wrong. That documentation is still there in 2013 though, so nobody seems to have done anything about it.

无论如何,你应该做的是这样的:

Anyway, what you should actually do is something like this:

NSFetchRequest *fetchRequest = ...
NSArray *result = [moc executeFetchRequest:fetchRequest error:&err];
result = [result filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"ALL contacts.uid != %@", contactUId]];

这将评估软件中的谓词.

This will evaluate the predicate in software.

这篇关于使用聚合操作崩溃:“ALL"在 Core Data iOS 应用程序中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆