Повторный вызов push для UINavigationController вызывает ошибку доступа - PullRequest
1 голос
/ 18 сентября 2010

У меня есть приложение TabView с вкладкой, у которой NavView является одним из видов. Это представление имеет вложенное представление с табличным представлением для хранения событий. Я включил кнопку «Добавить» в правом верхнем углу панели навигации и назначил IBAction для кнопки.

Цель состоит в том, чтобы показать страницу для добавления нового события, которое определяется файлом NIB, загруженным при создании экземпляра моего класса контроллера подкласса. Я также передаю managedObjectContext от родительского контроллера Nav.

Это работает в первый раз, но во второй раз, когда я нажимаю кнопку «Добавить», я получаю ошибку EXC_BAD_ACCESS. Я отладил до нажатия контроллера на навигационный контроллер, и я подтвердил, что именно здесь происходит исключение. Я прочитал документы, и там написано, что навигационный контроллер будет выдвигать контроллер, нажимая кнопку «назад», расположенную в верхней части навигационной панели. Я также знаю, что произойдет необработанное исключение, если я попытаюсь поместить то же представление в стек. Я даже пытался вернуться обратно к корню незадолго до нажатия, чтобы очистить стек, но все еще получал исключение при нажатии во второй раз.

Должен ли я высовывать это вручную (то есть навигационная кнопка "назад" на самом деле не выдает это) где-нибудь еще? Я также подтвердил, что экземпляр и контроллера nav, и нового экземпляра контроллера представления не пусты.

Вот фрагмент кода для кнопки «Добавить»:

- (IBAction) addEvent: (id)sender {

 // Here we'd instantiate an instance of our Add Event Controller to show the form that allows us to enter a new event.

 // We'd add the context to the class from here so that it can get to our Core Data


  EventEntryViewController *fvController = [[EventEntryViewController alloc] initWithNibName:@"AddEventView" bundle:nil];

 fvController.managedObjectContext = self.managedObjectContext;

 [self.navigationController pushViewController:fvController animated:YES];

 [fvController release];

 fvController = nil;

}

Спасибо за любую помощь.

Обновление:

ОК, я остановил исключение. Я попробовал очень простое представление без чего-либо, без IBOutlets или IBActions и класса контроллера, который не имел атрибутов. Это сработало, поэтому я решил, что это должно быть проблемой с моим EventEntryViewController. Это ничего не дало, и обратная трассировка показала, что он умирает от внутреннего представления представления, поэтому я даже не дошел до метода loadView, не говоря уже о любой другой части моего кода. У меня было несколько атрибутов класса, которые были инициализированы в предыдущей загрузке, и как добропорядочный гражданин я выпустил их в viewDidUnload () и освободил их в dealloc (). Когда я закомментировал сделку с моими атрибутами класса, это сработало!

Я был смущен этим и поместил строки NSLog () в viewDidLoad (), viewDidUnload () и dalloc (). Вот результаты двух последовательностей push после того, как я вынул dalloc из моих атрибутов класса:

2010-09-18 20:17:46.224 myFuel[6435:207] EventTableNavViewController: viewDidAppear
2010-09-18 20:17:51.391 myFuel[6435:207] **EventEntryViewController**: View Did Load // loading up my class
2010-09-18 20:17:53.954 myFuel[6435:207] EventTableNavViewController: viewWillAppear
2010-09-18 20:17:54.314 myFuel[6435:207] EventTableNavViewController: viewDidAppear
2010-09-18 20:17:54.315 myFuel[6435:207] **EventEntryViewController**: dalloc       // after the class should have been popped
2010-09-18 20:18:02.803 myFuel[6435:207] **EventEntryViewController**: View Did Load //loading up my class
2010-09-18 20:18:08.134 myFuel[6435:207] EventTableNavViewController: viewWillAppear
2010-09-18 20:18:08.494 myFuel[6435:207] EventTableNavViewController: viewDidAppear
2010-09-18 20:18:08.495 myFuel[6435:207] **EventEntryViewController**: dalloc    // after the class should have been popped

Я что-то здесь упускаю? Разве представление не должно вызывать viewDidUnload (), тем самым высвобождая атрибуты класса? Я вижу, как вызывается dealloc, но куда мне их высвобождать?

1 Ответ

0 голосов
/ 19 сентября 2010

Пара вещей, основанных на том, что вы сказали, хотя мне не совсем ясно, что вы делали.

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

Во-вторых, вы говорите, что «освободили их в dealloc» в связи с вашими «атрибутами класса», которые, как я понимаю, означают, что вы фактически вызываете dealloc для других объектов. Если так ... НЕ ДЕЛАЙТЕ ЭТОГО. Вы должны вызывать release только на тех объектах, которые вы сохранили, и редко когда у вас будет экземпляр, когда вы вызываете dealloc напрямую. Это потому, что dealloc будет вызываться в реализации объекта release, когда он будет выпущен в последний раз. В этом весь смысл системы удержания / выпуска.

...