正确的例子:
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
错误的例子:
- (void)dealloc {
[super dealloc];
[viewController release];
[window release];
}
在几乎所有其他情况下,当重写一个方法时,我会首先调用super的方法实现,在这种情况下,apple总是在最后调用[super dealloc]。为什么呢?
答案 0 :(得分:54)
它只是一个指导方针。您可以在[super dealloc]
之后调用其他说明。但是你不能再访问超类的变量,因为它们在你调用[super dealloc]
时被释放了。在最后一行调用超类总是安全的。
如果KVO和依赖(触发)键依赖已经释放的成员变量,它们也会产生副作用。
答案 1 :(得分:12)
我对iPhone的编程一无所知,但我认为这是因为需要以相反的顺序调用析构函数。在调用超类之前,您需要确保清除所有“垃圾”。如果你这样做,事情的其他方式会变得混乱。例如,如果析构函数需要访问超级析构函数已经释放的内存:
class X {
private Map foo;
function __construct() {
foo = new Map();
}
function __destruct() {
foo.free;
}
}
class Y extends X {
function __construct() {
super.__construct();
map.put("foo", 42);
}
function __destruct() {
super.__destruct();
if (map.containsKey("foo")) { // boooooooooom!
doSomething();
}
}
}
您可能不会在 代码中遇到此问题,因为“您知道自己在做什么”,但更好的做法是更安全,更好的做法。
答案 2 :(得分:5)
[super dealloc]释放对象使用的内存,包括viewController和window的指针。在释放它们之后参考变量充其量是危险的。
请参阅this answer。
答案 3 :(得分:2)
这是[super dealloc]必须为last的实际示例,否则对removeFromRunLoop的调用将导致崩溃。我不确定NSOutputStream的removeFromRunLoop中发生了什么,但在这种情况下它似乎可以访问'self'。
设定:
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
的dealloc:
- (void)dealloc {
if (outputStream) {
[outputStream close];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[outputStream release];
outputStream = nil;
}
delegate = nil;
[super dealloc]; // must be last!
}
答案 4 :(得分:1)
最后几乎有[super dealloc]
,因为它释放了超类的变量,无法再访问它们。
一个例外是如果你有一个UITableViewController的子类,它使用另一个类作为其表视图委托。在这种情况下,您必须在[super dealloc]
之后释放表视图委托,因为表视图引用了表视图委托,并且必须首先释放表视图。
答案 5 :(得分:1)
[到最后一篇文章]引用委托的tableView不会负责释放它自己的委托吗?我认为它在设置时保留它(所以你可以释放或自动释放它)它会照顾自己吗?
对于OP问题,如果我正在构建并且如果我正在破坏,我将总是超级优先打电话。我认为它“我希望超级构建它想要的东西,所以我可以在此基础上进行构建,并且在我自己清理之后,我希望超级能够最终完成。”实际上我使用的所有调用都在构建,除了dealloc,所以这就是为什么你总是会在我的dealloc代码中看到它。