7

我在某处读到-关于内存不足警告并放弃所有子视图的不可见视图(我认为=整个笔尖),您应该这样做:

-(void)dealloc {
    [anView release], anView = nil;
    [someImageView release], someImageView = nil;

    [super dealloc];
}

而不是

-(void)dealloc {
    [anView release];
    [someImageView release];

    [super dealloc];
}

在我调用 release 之后,将这些指针指向 nil(=“无对象”)的原因是什么?让我猜猜:由于某种原因,其他一些方法可能会保留视图(任何人都可以举例说明何时会发生这种情况?),然后发生 didReceiveMemoryWarning 事情,并且您释放了当前不可见的整个 nib+view(即在多视图应用程序中)。一旦用户想再次查看该视图,您将再次快速加载 nib,然后:它加载所有视图,连接插座,然后 BANG!您的其他保留视图现在挂起,没有任何指针在内存砖的某个地方孤独,导致大量内存泄漏,直到您的应用程序崩溃。

正确错误?

4

5 回答 5

14

原理比UIView更通用。确实它比 Objective-C/Cocoa-release方法更通用。它也适用于 C malloc()/free()内存函数。

当您不再需要某个对象或任何内存区域时,首先释放/释放它。然后,为了确保您不会再次使用它,您可以通过将 a 分配给nil对象或分配NULL给内存指针来清除访问此对象或内存区域的方法。

于 2009-04-30T08:37:08.460 回答
11

出于某种原因,其他一些方法可能会保留视图

除非您dealloc自己调用,否则只有在保留计数变为零时才会调用它。

请注意,在 Objective-C 中,向“对象”发送消息nil(通常)非常好。这样做不会使您的程序停止,但该消息会被忽略。但是,您不能向已释放的对象发送消息,这会导致崩溃。

因此,以下内容会给您一个错误:

[anView release];
[anView doSomething];

但是,这实际上没问题:

[anView release];
anView = nil;
[anView doSomething];

这是一个口味问题,但对于上述情况,您实际上可能更喜欢使程序崩溃,而不是想知道为什么 doSomething 没有执行......

另请参阅Apple 的Objective-C 2.0 编程语言简介中的向 nil 发送消息

于 2009-04-30T09:55:25.820 回答
4

-dealloc 方法在对象被释放时调用,之后不会执行对象上的其他方法。因此,将任何实例变量设置为 nil 在该对象之外都没有影响。

如果您在类中的其他地方释放对象(不使用 setter),则将实例变量设置为 nil 以防止其他地方的代码向该地址发送消息非常重要。

于 2009-04-30T21:03:07.993 回答
2

我经常使用这种模式:

- (void) showHelp: (id) sender
{
    if (helpController == nil)
    {
        helpController = [[HelpController alloc] initWithNibName: @"Help" bundle: [NSBundle mainBundle]];
    }
    [self presentModalViewController: helpController animated: YES];    
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
    [helpController release];
    helpController = nil;
}

几乎在我分配模态或“临时”视图控制器的所有地方。这样,如果我再次需要它,它就会挂起,但如果内存不足,它就会消失。

于 2009-04-30T17:07:07.687 回答
1

如果您的访问器具有与它们关联的属性 yoc 并作为更简洁的方法执行以下操作,而不是执行显式释放并设置为 nil:

- (void) dealloc
{
    self.retainedProperty1 = nil;
    self.retainedProperty2 = nil;
    self.copiedProperty = nil;
    self.assignedProperty = nil;
}

通过这种方式,您可以拥有更少重复的代码,因为合成代码会为您处理您的发布。

编辑:我应该指出你的属性不能是只读的,否则你会因为明显的原因得到编译器错误:)

于 2009-05-12T22:31:26.393 回答