Подкласс NSWindowController не будет выпущен в ARC

Я сталкиваюсь со странной ситуацией с NSWindowController. Я хочу, чтобы оконный контроллер был выпущен, но это не так. Кажется, это не соответствует моим ожиданиям в отношении поведения ARC.

Я создал простой подкласс оконного контроллера, PlainWindowController. Его интерфейс и реализация пусты:

#import <Cocoa/Cocoa.h>

@interface PlainWindowController : NSWindowController
@end

@implementation PlainWindowController
@end

Я создал с ним окно WindowController по умолчанию с именем PlainWindowController.xib, в котором уже установлено окно с подключением делегата и windowController.

В тесте я написал этот код:

PlainWindowController *strongWindowController = [[PlainWindowController alloc] initWithWindowNibName:@"PlainWindowController"];
__weak PlainWindowController *weakWindowController = strongWindowController;

[strongWindowController showWindow:nil];

strongWindowController = nil;
STAssertNil(weakWindowController, @"The window controller should have been deleted, wasn't");

Когда этот тест выполняется, слабая ссылка не ноль.

Если я пропущу showWindow это ноль. Если я использую init вместо initWithWindowNibName, это ноль.

Кто-нибудь знает, что здесь происходит? Заранее спасибо за любые рекомендации.

4 ответа

Решение

Как правило, вам не следует таить "ожидания" в отношении освобождения объектов, если они когда-либо передавались в другой код, который вы не контролируете.

Возможно, какао сохранило и затем автоматически освободило контроллер. Какао может сохранить контроллеры окна любых окон, которые показывают.

В общем, когда дело доходит до управления памятью Какао, вы должны убедиться, что ваш собственный код соответствует правилам (что ARC в основном делает для вас), и вы должны предполагать, что другой код следует правилам, но вы не можете предполагать, что другие код не сохраняет объекты за пределами того, где заканчивается ваш интерес. Вам в принципе не нужно заботиться о том, что делает другой код в отношении управления памятью.

Если вы действительно хотите знать, что происходит, запустите ваше приложение под инструментом Распределения и изучите историю сохранения / выпуска / автоматического выпуска вашего объекта после того момента, когда вы ожидали, что он был освобожден.

Нет никакой гарантии, что объект в ARC не был добавлен в пул автоматического выпуска, и в этом случае он не будет освобожден до конца текущего события.

В вашем случае я сильно подозреваю, что где-то внутри initWithWindowNibName: контроллер удерживается и автоматически освобождается.

Если вы действительно хотите, чтобы ваш объект был освобожден, просто создайте подкласс метода -dealloc и добавьте к нему NSLog или разбейте его.

У меня была похожая проблема при первом использовании ARC. К сожалению, я не помню деталей, так как это было больше года назад. В конце концов я обнаружил, что это проблема циклического сохранения, используя инструменты для мониторинга сохранения значений, хотя и без потери волос.

Я думаю, что настоящая проблема была с делегатом, который я исправил с @property (unsafe_unretained) id delegate;

Вчера я столкнулся с подобной проблемой в проекте на основе ARC - подкласс NSWindowController не освобождает и не запускает -dealloc. Я работал с Зомби, Распределения безрезультатно. Проблема была очень простой. Внутри окна находился подклассный элемент управления, и в этом элементе управления заголовочный файл подкласса.h свойство было определено как:

@property id delegate;

исправляя это

@property (nonatomic, weak) id delegate;

исправил проблему.

Другие вопросы по тегам