从内存存储中删除 Core Data 对象会将它们变成故障,但不会擦除它们
Posted
技术标签:
【中文标题】从内存存储中删除 Core Data 对象会将它们变成故障,但不会擦除它们【英文标题】:Deleting Core Data objects from in-memory store turns them into faults but does not erase them 【发布时间】:2013-05-08 23:59:50 【问题描述】:我有一个基于 NSInMemoryStoreType
存储的核心数据堆栈。而且我注意到删除对象并没有真正删除它们或使它们为零,而是只是将它们变成错误。
例如,(MyManagedObjectEntityClass 以及 标识符都是占位符):
MyManagedObjectEntityClass *o = [NSEntityDescription insertNewObjectForEntityForName:@"<MyManagedObjectEntityClass Entity Name>" inManagedObjectContext:self.localContext];
NSLog(@"\n%@", o);
[self.localContext deleteObject:o];
NSLog(@"\n%@", o);
将记录该对象仍然存在,只是它的数据是错误的。
在删除后添加[self.localContext save:nil];
也不会改变这一点。
我希望我可以在某个时候为nil
测试o
变量,在这种情况下我会重新加载该对象 - 但似乎我不能。
以防万一,是的,我知道我可以改为测试 o
是否为 -isFault
。但问题是,将此测试外推到 NSSet,我不能仅仅依靠 [[set anyObject] isFault]
来得出该集合中的所有对象都已被删除的结论(理想情况下,该集合的计数为 0,但所有对象仍然存在故障) .
所以我想知道是否有可能,或者我可以采取什么替代方法来测试对象是否已被删除,以对它们是托管对象这一事实透明。
【问题讨论】:
你试过用[o isDeleted]
测试吗?
事情是让我和 isFault 处于同一条船上。对象本身会从上下文中删除。如果我在删除后执行提取请求,则上下文不返回任何匹配项。问题实际上是,对客户端代码中保存的对象的任何引用(例如,视图控制器中的 NSArray,持有一堆托管对象)在删除后仍然在集合中,即使它们是错误的,它们仍然是对象,如果我针对 nil 进行测试或测试集合的计数。
可能是我尝试使用托管对象的方式超出了核心数据的范围。我在想也许可以编写一个类别或对集合进行子类化以使它们了解托管对象,但这可能效率极低。
阅读here关于无法完成故障
我的问题实际上是 C 语义(按值)与您刚刚链接的核心数据的条件和行为的组合。谢谢指点! (没有双关语)
【参考方案1】:
这实际上不是核心数据问题。 C(以及扩展的 Objective-C)不是那样工作的。
deleteObject:
方法接受一个参数,一个指向对象的指针。它可以改变对象(比如设置它的isDeleted
标志),或者它可以做与对象相关的其他事情(比如从它的托管对象上下文中删除它)。它不能改变指针本身的值。所以无论它做什么或应该做什么,C 说一旦它完成,你传入的指针仍然指向内存中的相同位置。因此,在这种语言中,该方法实际上不可能强制该指针为零。如果你想让它为零,你必须自己改变它。 (顺便说一句,实现该方法以获取指向指针参数的指针是可能的,这可以修改您的指针。这不会影响其他引用,例如数组中的引用,但是,所以这有点毫无意义)。
这就是isDeleted
方法是公共的原因,因此如果您在其他位置有指向此对象的指针,您可以在尝试使用它之前检查它是否已被删除。
如果这还不够方便(而且通常不是这样),Core Data 还提供了NSManagedObjectContextObjectsDidChangeNotification
和NSManagedObjectContextDidSaveNotification
。您可以在应用程序中的任何位置使用它们来获取上下文更改的通知,并以适当的方式响应(例如,更新数组)。这些通知都试图通过提供插入、更新和删除对象的列表来帮助您。尽可能使用这些来检查您是否确实需要更新您的参考资料。
【讨论】:
我知道 C/obj-C 与 C++ 语义之间的区别。但我想我是从老式 C 数组的角度来考虑的。类似于typedef struct int num; obj; int main() obj* a[3]; a[0] = malloc(sizeof(obj)); a[0]->num = 55; printf("\n%p", a[0]); free(a[0]); a[0] = NULL; printf("\n%p", a[0]); return 0;
的东西。谢谢!以上是关于从内存存储中删除 Core Data 对象会将它们变成故障,但不会擦除它们的主要内容,如果未能解决你的问题,请参考以下文章
如何删除 Core Data 存储中除一个对象之外的所有对象?