CoreData - 删除托管对象内的对象

CoreData - delete an object inside a managed object

我正在使用 CoreData 在对话中保留消息列表。

Conversation 是一个具有消息数组的托管对象。 在一种情况下,我试图删除对话中的所有消息。

for (UQMessage * message in self.tempConversation.chatMessages){
            [self.tempConversation.managedObjectContext deleteObject:message];
            error = nil;
            [self.tempConversation.managedObjectContext.persistentStoreCoordinator lock];

            if (![self.tempConversation.managedObjectContext save:&error]) {
                NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]);
                return;
            }
            [self.tempConversation.managedObjectContext.persistentStoreCoordinator unlock];
}

当我检查

self.tempConversation.chatMessages.count

没有任何变化。

当我尝试添加消息和删除对话本身时,一切都运行良好。但我似乎无法删除一条消息。

是否可以这样做,因为我不是要删除托管对象本身,而是要删除其中的另一个对象? 如果没有, Anyway around 呢?

编辑:

Messages 是 Conversation 中的一个 NSOrderedSet。 我发现这个有效(取自 thread):

NSMutableOrderedSet *mutableItems = (NSMutableOrderedSet *)items.mutableCopy;
[mutableItems addObject:anItem];
items = (NSOrderedSet *)mutableItems.copy;

尽管我不确定这是否可行。

你不应该,永远改变你正在迭代的数组。根据 fast enumeration docs"It is not safe to remove, replace, or add to a mutable collection’s elements while enumerating through it. If you need to modify a collection during enumeration, you can either make a copy of the collection and enumerate using the copy or collect the information you require during the enumeration and apply the changes afterwards."

在枚举期间改变数组的结果是不确定的,我的猜测是核心数据可能只是举起手来而不做任何事情。可变副本起作用的原因是因为您正在处理一个副本,而不是您正在枚举的集合。

我会重写您的逻辑以遵循枚举文档中规定的准则,并在循环之外进行更改。

编辑:其他想法

  • 为什么要锁定和解锁持久存储?它自己处理。

  • 您可以在 for in 中安全地调用 delete(但我不会),然后在外部调用 save,因为 save 才是真正执行删除的操作。

更多想法

(从评论中抄录)-考虑了几天然后回来,我猜你没有彻底崩溃的原因是快速枚举正在对你的关系数组进行深度复制重新工作,因为在 MOC 上调用保存将增加一个内部版本,然后 应该 return 所有现有的托管对象都反对要重新获取的错误对象下次访问。实际上,从 "application health" 的角度来看,您在此处获得的这段代码实际上非常危险。

如果您查看核心数据关系的文档,我想您会发现更简单的做法是将关系的关系删除规则设置为 "Cascade"。当您删除对话时,这将为您删除所有消息。这是参考:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdRelationships.html#//apple_ref/doc/uid/TP40001857-SW1

首先,关于 Matt S. 的回答,您没有修改 self.tempConversation 因此您不必担心在迭代时改变数组。

另一方面,如果您的问题是 self.tempConversation.chatMessages.count 没有改变。那是正常的。您正在从 NSManagedObjectContext 中删除对象。但是数组没有被修改。因此,该数组仍然具有托管对象,但该托管对象已被删除。有那么容易吗。它是僵尸管理对象,因为它已从 MOC 中删除。尽管如此,该对象还没有从数组中删除。因此,您有一个已删除的 属性 设置为 YES 的托管对象。它不再是 MOC 的一部分。