Подтвердить что ты не робот

Почему мне нужно называть super -dealloc последним, а не первым?

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

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

неверный пример:

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

Вот пример, где [super dealloc] должен быть последним, иначе вызов removeFromRunLoop приведет к сбою. Я не уверен, что происходит внутри NSOutputStream removeFromRunLoop, но в этом случае он, похоже, получает доступ к "я".

Настройка:

[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!
}

Ответ 5

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

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

Ответ 6

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

Что касается вопроса OP, я всегда буду называть super первым, если я буду строить, и вызовет super last, если я разрушу. Я думаю об этом как "Я хочу, чтобы супер построить то, что он хочет, чтобы я мог это сделать, и я хочу, чтобы супер срывался последним после того, как я убираюсь после себя". Фактически все вызовы, которые я использую, строят, хотя, кроме dealloc, поэтому вы всегда будете видеть это в моем коде dealloc.