Почему я должен вызывать super -dealloc последним, а не первым? - PullRequest
29 голосов
/ 26 мая 2009

правильный пример:

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

неправильный пример:

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

Почти во всех других случаях при переопределении метода я бы сначала вызвал реализацию метода super, в этом случае apple всегда вызывает [super dealloc] в конце. Почему?

Ответы [ 6 ]

54 голосов
/ 26 мая 2009

Это просто руководство. Вы можете вызвать другие инструкции после [super dealloc]. однако вы больше не можете получить доступ к переменным суперкласса, потому что они освобождаются, когда вы вызываете [super dealloc]. Всегда безопасно вызывать суперкласс в последней строке.

Также KVO и зависимые (запускаемые) ключи могут вызывать побочные эффекты, если они зависят от уже освобожденных переменных-членов.

12 голосов
/ 26 мая 2009

Я ничего не знаю о программировании для 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();
        }
    }
}

Возможно, вы не столкнетесь с этой проблемой в вашем коде, потому что "вы знаете, что делаете", но в целом безопаснее не делать такие вещи.

5 голосов
/ 26 мая 2009

[super dealloc] освобождает память, используемую вашим объектом, включая указатели на viewController и window. Ссылка на переменные после их освобождения опасна в лучшем случае.

См. этот ответ .

2 голосов
/ 31 января 2010

Вот фактический пример, когда [super dealloc] должен быть последним, в противном случае вызов removeFromRunLoop вызовет сбой. Я не уверен, что происходит внутри removeFromRunLoop из NSOutputStream, но, похоже, в этом случае он обращается к '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!
}
1 голос
/ 06 августа 2010

[к последнему сообщению] Не будет ли tableView, ссылающийся на делегата, отвечать за освобождение своего собственного делегата? Я бы подумал, что он сохранился, когда установлен (чтобы вы могли освободить или автоматически выпустить его), и он позаботится о себе?

Что касается вопроса ОП, я всегда буду сначала вызывать супер, если я создаю, и вызывать супер последний, если я разрушаю. Я думаю об этом как «я хочу, чтобы супер построил то, что он хочет, чтобы я мог на этом опираться, и я хочу, чтобы супер разрушали в последнюю очередь после того, как я уберу за собой». Хотя фактически все вызовы, которые я использую, создаются, кроме dealloc, поэтому вы всегда будете видеть это в моем коде dealloc.

1 голос
/ 02 августа 2009

У вас практически почти есть [super dealloc] в конце, потому что это освобождает переменные суперкласса, и к ним больше нельзя получить доступ.

Единственное исключение - если у вас есть подкласс UITableViewController, который использует другой класс в качестве своего делегата табличного представления. В этом случае вы должны освободить делегат табличного представления после [super dealloc], потому что табличное представление ссылается на делегата табличного представления, и табличное представление должно быть сначала освобождено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...