我使用CoreData来保留对话中的消息列表。
Conversation是一个具有Message数组的managedObject。 在一种情况下,我试图删除对话中的所有消息。
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
没有任何改变。
当我尝试添加消息时,以及当我删除对话本身时,一切都运行良好。但我似乎无法删除单个邮件。
是否可以这样做,因为我没有尝试删除托管对象本身,而是删除其中的另一个对象? 如果不是,不管怎么说呢?
修改:
Messages是Conversation中的NSOrderedSet。 我发现了这个作品(取自thread):
NSMutableOrderedSet *mutableItems = (NSMutableOrderedSet *)items.mutableCopy;
[mutableItems addObject:anItem];
items = (NSOrderedSet *)mutableItems.copy;
虽然我不确定这是否可行。
答案 0 :(得分:2)
首先,关于Matt S.的回答,你没有修改self.tempConversation,所以你不必担心在迭代时改变数组。
另一方面,如果你的问题是self.tempConversation.chatMessages.count没有改变。这很正常。您正在从NSManagedObjectContext中删除对象。但是阵列没有被修改。因此,该数组仍然具有托管对象BUT,该托管对象被删除。这很容易。它是一个僵尸管理对象,因为它已从MOC中删除。然而,该对象尚未从阵列中删除。因此,您有一个托管对象,其属性已删除设置为YES。而且它不再是MOC的一部分了。
答案 1 :(得分:1)
你永远不应该永远改变你正在迭代的数组。根据{{3}}:“在枚举时删除,替换或添加可变集合的元素是不安全的。如果您需要在枚举期间修改集合,则可以复制收集和枚举使用副本或收集您在枚举期间所需的信息,然后应用更改。“
在枚举期间改变数组的结果是未定义的,我的猜测是核心数据可能只是抛弃它而没有做任何事情。可变副本的工作原因是因为你正在处理一个副本,而不是你要枚举的集合。
我会重写您的逻辑,以遵循枚举文档中规定的准则,并在循环之外进行更改。
编辑:其他想法
你为什么要锁定&解锁持久性商店?它自己处理。
您可以在for in中安全地调用delete(但我不会),然后调用save out,因为save实际上是删除。
更多想法
(从评论中抄写) - 在考虑了几天然后再回来之后,我的猜测是你没有直接崩溃的原因是快速枚举是在你正在工作的关系数组上进行深层复制on,因为在MOC上调用save将增加内部版本,然后应该返回所有现有的被管理对象,以便在下次访问时重新获取故障对象。实际上,从“应用程序健康”的角度来看,这里的代码实际上非常危险。
答案 2 :(得分:0)
如果你查看核心数据关系的文档,我想你会发现更简单的事情就是将关系的关系删除规则设置为“Cascade”。这将在您删除对话时删除所有消息。以下是参考:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdRelationships.html#//apple_ref/doc/uid/TP40001857-SW1