在 Objective-C 中释放托管对象
Posted
技术标签:
【中文标题】在 Objective-C 中释放托管对象【英文标题】:Releasing Managed Objects in Objective-C 【发布时间】:2010-01-07 03:13:09 【问题描述】:好的,请容忍我对我的情况的描述:
我有一个核心数据模型(在简化的描述中)包括一个 GridManager 对象。 GridManager 拥有一组 Grid 对象(通过一对多关系)。 Grid 对象包含一组 Cell 对象(通过一对多关系)。
在我的应用程序中,我有一个 GridView,其中包含一系列子视图(CellView 类型)。 GridView 有一个presentedGrid 属性,而CellView 有一个representedCell 属性(都是非原子的,保留)。在GridView的setRepresentedGrid方法中,我将每个CellView(GridView的子视图)的representedCell属性设置为representedGrid中的一个单元格。
现在,我有两个问题:
首先,由于单元格和网格都是托管对象,我还需要释放GridView和CellView类的representedGrid和representedCell属性吗?我想我会这样做(就像任何保留的属性一样),但有一次我认为这会导致我的应用程序出现问题 - 嗯......只是想,因为我编写了自己的设置器,而我实际上并没有保留网格/单元格,也许我不需要释放它们?
其次,gridManager 一次只有一个网格处于活动状态。当我将 gridView.representedGrid 从一个网格切换到另一个网格时,我如何“释放”第一个网格(及其关联的单元格),以便它不会不必要地占用内存(假设我们正在谈论托管对象)。
非常感谢!
【问题讨论】:
你为什么要编写自定义的 getter 和 setter? 参见下面的 cmets——我希望视图在设置了代表迷宫时处理某些设置功能——我认为这是需要为属性自定义设置器的标准原因。跨度> 【参考方案1】:据我了解,您应该并且可以避免自定义 getter 和 setter,然后您可以让核心数据去做这件事,而不必担心保留/释放。
至于减少内存开销,您可以使用此方法要求核心数据将您的对象变为故障:refreshObject:mergeChanges:
在此处查看 Apple 文档:http://gemma.apple.com/mac/library/documentation/Cocoa/Conceptual/CoreData/index.html。这一切都在那里,希望我能够为您提供合适的条款。
希望对你有所帮助。
【讨论】:
您对 refreshObject 的评论刷新了我的记忆——我现在回想起我第一次研究 Core Data 时读到的关于它的内容。谢谢!【参考方案2】:如果您的 setter 保留托管对象,那么您需要释放它们以匹配保留/释放。但是,根据应用程序的设计方式,您可能不需要保留托管对象。
如果没有看到所有代码,很难给出可靠的建议,但您可以使用分析器检查泄漏,使用仪器确保您的内存没有增加失控等。最后但并非最不重要的是,您可以关闭保留,将它们切换到分配,看看它是否崩溃。由于NSManagedObjectContext
将保留对象,因此您的视图很有可能根本不需要保留NSManagedObject
实例。
【讨论】:
【参考方案3】:是的,您需要在您的 dealloc 方法中释放您的代表网格和代表单元属性。如果您不这样做,则保留/释放方法将无法平衡 - 您的设置器将保留对象,并且没有相应的释放,该对象将永远不会被释放。
如果编写得当,retain setter 将释放其旧值并保留新值。所以设置gridView.representedGrid时不需要释放旧网格。
出于好奇,您为什么要编写自己的 setter?
【讨论】:
我正在编写自己的设置器,以便通过将 GridView 指向其网格,它会自动设置其 CellView 子视图以表示网格中的单元格。它还将自己添加为来自网格的通知的观察者(因此视图可以在网格更改时更改)。在一般编程概念中,属性(而不是直接访问字段)的原因之一是提供定制的 getter/setter,当访问关联的属性时可以执行必要的功能。当然,我综合了我的绝大多数属性。以上是关于在 Objective-C 中释放托管对象的主要内容,如果未能解决你的问题,请参考以下文章
在一个线程中创建并在objective-C中传递给另一个线程的自动释放对象
为啥在 Objective-C 中执行 alloc 和 init 在单独的语句中会导致对象根据 Xcode 静态分析器被释放?