查看控制器/内存管理

时间:2011-06-21 20:26:13

标签: ios objective-c memory-management viewcontroller

我对视图控制器中的内存管理有点困惑。

假设我有这样的头文件:

@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之后会有效吗?你如何在你的应用程序中做到这一点?

感谢您的回答;)

3 个答案:

答案 0 :(得分:1)

虽然alloc-retain调用在viewDidLoadviewDidUnload中平衡,并且在内存方面证明没有问题,但只获取一次所有权并放弃一次而不是两次

- (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是您唯一需要担心的地方;在其他地方使用属性访问者。)