Подкласс 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;
исправил проблему.