2009-11-18 2 views
2

Я получаю сообщения об утечке памяти в своем приложении, но я не могу точно определить, что происходит. У меня есть функция, которая выводит старый вид и свопирует в новое представление. Я не использую NavControllers или любые @properties; Я управляю своим окном верхнего уровня напрямую.Отслеживание утечек памяти какао

-(void)swapInView:(UIViewController*)newViewController 
{ 
    [currentViewer.view removeFromSuperview]; 
    printf("Old viewController (%p) has count of %d; now releasing\n", 
     currentViewer, [currentViewer retainCount]); 
    [currentViewer release]; 
    currentViewer = 0; 

    currentViewer = newViewController; 
    [currentViewer retain]; 

    [mainWindow addSubview:currentViewer.view]; 
    [mainWindow bringSubviewToFront:currentViewer.view]; 
} 

При запуске кода, я показываю, что текущий контроллер зрения быть высвобождены, а затем мой метод dealloc для этого вида контроллера вызывался. Но, приборы/утечки все еще сообщают об этом как утечку. Например, я получаю эту распечатку:

Old viewController (0x119f80) has count of 1; now releasing 
Deallocating WelcomeScreenViewController 

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

Мой внешний код выглядит примерно так:

MyViewController *theViewController = [[MyViewController alloc] 
             initWithNibName:nil 
               bundle:nil]; 
[GameMaster swapInNewView:theViewController]; 
[theViewController release]; 

Кто-нибудь есть какие-либо предложения о том, как отследить, что происходит? Я использую SDK 3.1.2, но я также видел это на более ранних SDK.

+0

Какая конкретная строка говорит о утечке? –

+0

[mainWindow addSubview: currentViewer.view]; –

+0

Итак, кажется, что 'mainWindow' просачивает добавленный под-просмотр. Вы вызываете выпуск на 'mainWindow' в какой-то момент? –

ответ

3

Huh. Это было весело. Я написал быстрый тест, чтобы убедиться, что ни один из нас не сумасшедший.

В конце концов, все сводится к вызывающему коду:

[[MyViewController alloc] initWithNibName:nil bundle:nil]; 

При инициализации контроллер представления, его view объект еще не был определен, и не будет определен до тех пор, пока требуется.

Поскольку вы указываете nil для имени ниба, вы должны переопределить loadView в своем подклассе UIViewController, чтобы правильно установить объект вида. См. Apple's documentation.

По умолчанию реализация loadView, по-видимому, выполняет некоторые закулисные магии, и эта магия может привести к утечке памяти.

Итак: когда вы делаете этот призыв:

[mainWindow addSubview:currentViewer.view]; 

Вы на самом деле делаете два звонков:

One: currentViewer.view, что приводит к вызову [currentViewer loadView] и
Два: [mainWindow addSubview:...] , который пытается добавить вновь загруженное представление.

Утечки идентифицируют эту линию из-за первого вызова, а не второго.

Чтобы проверить, просто измените метод loadView в ваших пользовательских UIViewController подклассов:

- (void)loadView 
{ 
    [self setView:[[UIView new] autorelease]]; 
} 

Это предотвращает вызов по умолчанию loadView и теперь больше нет утечек.

Очевидно, что после того, как вы разработаете это приложение дальше, вам нужно будет поставить что-то более значимое в loadView или использовать наконечники.

+0

Фантастический! Кажется, что это исправлено. Это заканчивается (я неосознанно скопировал это из примера кода Apple), что, если вы передадите «nil» в initWithNibName, он будет искать файл nib с тем же именем, что и класс, и загрузить его. Но, по-видимому, это тоже утечка памяти ... –

0

Примечания документация для метода removeFromSuperview:

«отсоединяет приемник от его надтаблицы и его окна, снимает его с ответчика цепи, и аннулирует его курсор прямоугольники Приемник также выпущен.»

Я не уверен, если это ваша проблема или нет, но делать:

[exampleViewController.view removeFromSuperview]; 
[exampleViewController release]; 

в моем приложении вызывает замедленное сбой из-за чрезмерное высвобождением объекта.

+0

Правда, но я сохраняю viewController сам, когда я его устанавливаю, а затем освобождаю после того, как я его удалю, поэтому я не сбой. –

Смежные вопросы