为什么我必须最后调用super -dealloc,而不是先调用?

时间:2009-05-26 09:44:50

标签: iphone cocoa-touch memory-management uikit

正确的例子:

- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

错误的例子:

- (void)dealloc {
    [super dealloc];
    [viewController release];
    [window release];
}

在几乎所有其他情况下,当重写一个方法时,我会首先调用super的方法实现,在这种情况下,apple总是在最后调用[super dealloc]。为什么呢?

6 个答案:

答案 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代码中看到它。