2010-01-17 4 views
0

Я пытаюсь реализовать свою собственную версию NSViewController (для обратной совместимости), и я столкнулся с проблемой с привязками: поскольку привязки сохраняют свою цель, у меня есть круг сохранения всякий раз, когда я связываюсь через File's владелец.Как NSViewController избегает утечки памяти привязок? [иметь пример приложения]

Итак, я думал, что просто удалю мой взгляд из своего супервизора и выпущу объекты верхнего уровня, и это позаботится о привязках, потому что мой контроллер больше не держится за представления, поэтому они освобождают я и я могу уйти. Но почему-то мой диспетчер просмотров по-прежнему не освобождается. Вот пример приложения экспонирование проблемы:

http://dl.dropbox.com/u/34351/BindingsLeak.zip

Построить его, запустить его, и ударил Cmd-K («Создание СИБ» в меню «Edit»), чтобы загрузить СИБ в пустое окно. Нажмите Cmd-K снова, чтобы выпустить первый контроллер представления (TestNibOwner) и загрузить новый. Однако старый контроллер просмотра не освобождается.

Снимите привязку «значение» на флажке, и она будет выпущена просто отлично.

Если вы установили точки останова при переопределении релиза/сохранения/автоопределения, вы увидите, что _NSBindingInfo сохраняет TestNibOwner, но никогда не выпускает его в случае утечки.

Кто-нибудь знает, как это исправить?

+0

К сожалению, я не хочу, чтобы загрузить проект первого в помочь тебе. Можете ли вы предоставить код? –

ответ

1

Одна вещь, которую я сделал для той же проблемы, - создать прокси-сервер NSObjectController внутри моего nib. Мой NSViewController-подобный класс имеет указатель на этот прокси, и все привязки связаны через него. Когда я хочу очистить контроллер представления, я затем сделаю [selfProxy setContent: nil] на контроллере объектов и отпустите контроллер вида. В этом случае прокси-сервер NSObjectController действует в этом случае как авто-unbinder.

Это более ручная работа, и вы не можете просто отпустить представление самостоятельно, но оно решает проблему сохранения.

я предлагаю вам сделать это:

-(void) releaseTopLevelObjects 
{ 
    // Unbind the object controller's content by setting it to nil. 
    [selfProxy setContent:nil]; 

    NSLog(@"topLevelObjects = %@", topLevelObjects); 
    [topLevelObjects release]; 
    topLevelObjects = nil; 
} 

В вашем СИБ, привязок будет происходить через путь, как:

selfProxy.content.representedObject.fooValue 
+0

Спасибо! Я видел много хакерских попыток исправления в Интернете, но это обходной путь, который я действительно посмел бы отправить. Слишком плохо, но нет * реального * способа сделать авто-развязывание. – uliwitness

0

Когда вы удаляете свой вид из своего супервизора, вы также отправляете ему другое сообщение -release? Он был создан путем unarchive от nib, не так ли?

+0

Да, releaseTopLevelObjects освобождает представление (и любые другие незакрепленные объекты, которые могут быть там). По крайней мере, это то, что он должен делать. – uliwitness

2

Выполнение небольшого расследования с дампом класса и друзьями, похоже, что у Apple есть частный класс под названием NSAutounbinder, который заботится об этой грязной работе для таких классов, как NSViewController и NSWindowController. Не могу сказать, как это работает или как его реплицировать.

Итак, я не могу ответить на ваш вопрос о том, как предотвратить цикл сохранения для произвольных привязок в загруженном nib, но, возможно, это утешение, чтобы знать, что Apple обманывает, и вы ничего не пропустите очевидно. :-)