核心数据 - 如何检查托管对象的属性是否已取消分配?

时间:2010-04-13 01:17:47

标签: iphone objective-c core-data nsmanagedobject memory-management

我创建了一个使用核心数据的程序,它运行得很漂亮。

我已经尝试将所有核心数据方法调用和获取例程移动到一个自包含的类中。然后我的主程序实例化该类并对该类进行一些基本的方法调用,然后该类在幕后完成所有核心数据。我遇到的是,有时我会发现当我从上下文中获取托管对象时,我将拥有一个有效的对象,但是它的属性已被释放,我将导致崩溃。我玩僵尸并寻找内存泄漏,我收集的是运行循环可能负责释放内存,但我不确定。

有没有办法确定是否已释放该内存并强制核心数据在需要访问时将其恢复?我的managedObjectContext永远不会被释放,而fetchedResultsController也不会被释放。

我想我可能需要使用[managedObjectContext refreshObject:mergeData:]方法或[managedObjectContext setRetainsRegisteredObjects:]方法。虽然,我的印象是最后一个可能不是最好的选择,因为它会更加记忆密集(根据我的理解)。

当我将核心数据调用移动到另一个类文件时,这些错误才会弹出,并且当它们出现时它们是随机的。

任何见解都将受到赞赏。

-Ryan

4 个答案:

答案 0 :(得分:1)

对我而言,就像你没有保留想要一直闲逛的物品一样。如果你这样做:

NSArray *array = [moc executeFetchRequest:request error:&error];

您不拥有返回的数组,并且当当前的自动释放池耗尽时,它很可能会消失。当运行循环完成处理当前事件时会发生这种情况。

所有这些都是猜测。如果你想要一个正确的答案,你需要发布你的代码。

答案 1 :(得分:1)

根据您的描述很难知道问题是什么,但您可能希望查看Core Data memory management guide。您不必担心托管对象及其实体的内存管理(它们会自动获取和出现故障)。当你谈到“属性”时,你的意思是由ivars支持的自定义属性吗?如果是,则根据需要releasedidTurnIntoFault d alloc d(可能在访问者中)。

答案 2 :(得分:1)

我正在努力解决类似的问题。我正在使用托管对象类,并希望根据用户输入设置其属性。但有时候属性,有时候整个托管对象都被解除分配。

阅读Apple文档http://developer.apple.com/library/IOs/#documentation/Cocoa/Conceptual/CoreData/Articles/cdMemory.html“管理对象上下文的角色”一章后,我了解到每个运行循环完成后都会释放托管对象。

有设置的黄金建议

[myMangedObjectContext setRetainsRegisteredObjects:YES];

(我必须在我的视图控制器的init方法(对我来说是initWithNibName)中设置它。)

您还应该考虑保留您需要的对象,如文档中所述。但是请自己阅读。

如果我不对,请纠正我。

答案 3 :(得分:0)

我还创建了一个处理所有CoreData抓取和东西的类。我遇到了几个问题,所以这里有一些提示。 (如果我在这些示例中出现任何内存管理错误,请告诉我们。)

两件事:


1)在CoreData处理程序类中创建了一个“fetchFiredObject”方法。所以当我想得到一个包含所有变量的托管对象并且是一个“完全羽毛的鸟”时,可以这么说而不是:

aManagedObject *myManagedObject = [myCoreDataHandler.managedObjectStorageArray objectAtIndex:1];
int x = myManagedObject.someVariable.intValue;

相反,我做了:

aManagedObject *myManagedObject = [myCoreDataHandler fetchFiredObjectAtIndex:1];
int x = myManagedObject.someVariable.intValue;

在myCoreDataHandler的fetchFiredObjectAtIndex:i方法中,我们进入数组,在索引i处找到对象键,然后对该对象键执行fetchRequest,并返回新获取的managedObject,使其不具有发生故障或解除分配等等:D


2)当我创建一个新的子viewController时,我在创建时从父级填充其“myCoreDataHandler”值。但是,这会发生在创建新viewController的代码行之后的后续代码行中。因此,子视图中的任何尝试使用myCoreDataHandler方法的viewDidLoad中的代码都将返回空对象,因为viewDidLoad在父代的下一行代码之前完成,其中它设置了子对象中全局变量的值。因此,请确保您没有从viewDidLoad或viewDidLoad调用的任何本地方法访问“核心数据处理对象”!而是在创建新的viewController之后从父级调用它们。