#iphone #objective-c #memory-leaks
#iPhone #objective-c #утечки памяти
Вопрос:
Я работаю над приложением, в котором есть основной вид, который хочет создавать дочерний вид при нажатии кнопки. Поэтому, когда я получаю событие button, MainViewController запускает дочернее представление, вызывая initWithNibName и сохраняя childViewController в ivar . Затем я показываю дочернее представление, прикрепляя анимацию и устанавливая childVC.view.hidden = NO .
Это работает, но я заметил, что childViewController так и не был выпущен после закрытия childView. Я понял, что количество сохранений childVC увеличилось с 1 до 2 при первом доступе к дочернему представлению. Таким образом, что-то в процессе загрузки nib, похоже, снова сохраняет мой дочерний элементvc (в дополнение к первоначальному сохранению, которое я ожидаю во время инициализации объекта).
Может кто-нибудь помочь мне выяснить, почему дочерний файл сохраняется дополнительное время, и как я могу убедиться, что он полностью освобождается, когда я хочу закрыть дочернее представление?
Редактировать: вот некоторый код, только немного упрощенный. Это методы родительского контроллера представления.
-(IBAction)onLaunchChildButtonTouched:(id)sender
{
m_childViewController = [[ChildViewController alloc] initWithNibName:@"ChildViewController" bundle:nil];
[m_childViewController setParentDelegate:self]; // this is a weak reference
// m_childViewController retain count here is 1, as expected
m_childViewController.view.hidden = YES;
// m_childViewController retain count is now 2, not expected
[self.view addSubview:m_childViewController.view];
[self addTransitionEntrDir:YES]; // code omitted
m_childViewController.view.hidden = NO;
}
-(void)onChildWantsToClose:(id)child
{
NSAssert( child == m_childViewController, @"unexpected childVC" );
// if child view is now hidden, we should remove it.
if( m_childViewController != nil amp;amp; m_childViewController.view.hidden )
{
[m_childViewController.view removeFromSuperview];
[m_childViewController release]; m_childViewController = nil;
// BUG: m_childViewController retain count is still 1 here, so it never gets released
}
}
Комментарии:
1. может быть, показать ваш фактический код?
2. Показ некоторого кода поможет привести к этому Q.
3. обновлено исходное сообщение с некоторым кодом.
Ответ №1:
Без кода трудно сказать точно, но вы уверены, что не присваиваете ChildVC
retain
свойству какого-либо другого объекта? Это объясняет неожиданное retain
, что вы видите.
Извините за предыдущий ответ, где я пытался передать это же сообщение, но я все перепутал.
СТАРЫЙ ОТВЕТ:
имейте в виду, что view
свойство a UIViewController
сохраняется:
view
Представление, которым управляет контроллер.
@property(неатомный, сохранить) UIView * просмотр
итак, если вы назначаете ему так:
childVC.view = [[xxxxx alloc] initWithNibName:…];
это объясняет, что вы видите.
Используйте вместо этого:
childVC.view = [[[xxxxx alloc] initWithNibName:…] авторелиз];
Комментарии:
1. Спасибо за ваш ответ. Я использую initWithNibName для инициализации ViewController, а не view . Затем (согласно документам) свойство View автоматически загружается из кончика при первом доступе к нему. Я не выполняю автоматическое освобождение ViewController, но я вручную освобождаю его, когда дочернее представление закрыто. Проблема, похоже, в том, что дочерний файл сохраняется дополнительное время, и я не могу понять, почему.
Ответ №2:
Я обнаружил проблему, дырявый childViewController создавал экземпляр объекта, который сохранял ссылку на него.
Интересно то, что я не просто забыл выпустить эту ссылку. У меня был вызов для его освобождения, но этот код никогда не выполнялся, потому что предполагалось, что viewDidUnload запустится и даст мне шанс освободить все, но этого не произошло. Вместо этого я поместил свой код deinit в dealloc, и теперь он работает.
Комментарии:
1. Обычная область, в которой это происходит, — это когда вы
addObserverForName:object:queue:usingBlock:
NSNotificationCenter
внутриviewDidLoad
, со ссылками наself
, но только removeObserver внутриdealloc
. Dealloc никогда не будет вызываться по определению, потому что блок будет сохраненself
. Вы можете сделать слабую ссылку наself
, чтобы помочь обойти эту проблему, Или подписаться / отказаться от подписки на уведомления вviewWillAppear
иviewDidDisappear
и т. Д.