我对视图控制器中的内存管理有点困惑。
假设我有这样的头文件:
@interface MyController : UIViewController {
NSMutableArray *data;
}
@property (nonatomic, retain) NSMutableArray *data;
@end
和.m文件看起来像这样:
@implementation MyController
@synthesize data;
- (void)dealloc
{
[self.data release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.data == nil)
self.data = [[NSMutableArray alloc] init];
}
- (void)viewDidUnload
{
[super viewDidUnload];
[self.data release];
self.data = nil;
}
从正确的内存管理角度来看,这样可以吗?通过内存警告dealloc之后会有效吗?你如何在你的应用程序中做到这一点?
感谢您的回答;)
答案 0 :(得分:1)
虽然alloc-retain
调用在viewDidLoad
和viewDidUnload
中平衡,并且在内存方面证明没有问题,但只获取一次所有权并放弃一次而不是两次
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.data == nil)
self.data = [NSMutableArray array];
}
和
- (void)viewDidUnload
{
[super viewDidUnload];
self.data = nil;
}
答案 1 :(得分:1)
我们无法保证viewDidUnload
会被调用。与成对调用的init / dealloc不同,viewDidUnload
被不确定地调用。只有在内存不足并且您的视图不是活动视图时才会调用viewDidUnload
。
根据您的模型的创建方式及其在内存中的含义,您可能更有意义 来摆脱它。这样的一个示例可能是重新创建该数据可能涉及昂贵的Web服务调用。因此,必须等待重新创建数据是一种糟糕的用户体验。如果必须绝对采用,更好的策略可能是将数据缓存到磁盘,以便您可以轻松地重建它。
viewDidUnload
应该只包含清理IBOutlet
并清除易于恢复的数据。
答案 2 :(得分:1)
来自-viewDidUnload
的这些行都发布了data
:
[self.data release];
self.data = nil;
由于您在第二行使用属性设置器,并且data
是保留属性,因此setter将释放data
。这是一个过度释放,它会立即或稍后导致崩溃,具体取决于其他对象是否也保留该对象。要修复,只需删除第一行并依赖setter做正确的事情。
另一方面,-dealloc
方法不应该像现在一样使用setter。你应该改变:
[self.data release];
为:
[data release];
data = nil; // this line isn't strictly necessary, but often considered good form
这里的推理是,可以想象这个类可以被子类化,并且有人可能会以这样的方式覆盖属性setter,使得它具有一些副作用,当副对象被释放时可能会导致问题。您应该直接访问ivar - 请注意我已经离开了“自我”。所以我们要处理的是ivar,而不是属性访问者。 (-init
和-dealloc
是您唯一需要担心的地方;在其他地方使用属性访问者。)