Сбой UINavigationController из-за нажатия и выталкивания UIViewControllers

Проблема: у меня есть UINavigationController как подвид UIWindow, класс rootViewController и пользовательский класс MyViewController. Следующие шаги получат Exc_Bad_Access, воспроизводимый на 100%.:

[myNaviationController pushViewController:myViewController_1stInstance animated:YES];
[myNaviationController pushViewController:myViewController_2ndInstance animated:YES];

Дважды нажмите левый задний элемент tapBarItem (выдвиньте два экземпляра myViewController), чтобы отобразить rootViewController.

После мучительных 1/2 дня проб и ошибок я наконец понял ответ, но также задаю вопрос.

Решение. Я объявил многие объекты в .m-файле как ленивый способ объявления частных переменных, чтобы не загромождать .h-файл. Например,

#impoart "MyViewController.h"
NSMutableString*variable1;

@implement ...

-(id)init
{
   ...
   varialbe1=[[NSMutableString alloc] init];
   ...
}

-(void)dealloc
{
   [variable1 release];
}

По некоторым причинам ОС iphone может потерять отслеживание выделения памяти для этих «ленивых частных» переменных, когда представление myViewController_1stInstance выгружается (но все еще находится в стеках навигационного контроллера) после загрузки представления myViewController_2ndInstance. В первый раз, чтобы коснуться назад tapBarItem, все в порядке, так как представление myViewController_2ndInstance все еще загружено. Но второе нажатие на задний tapBarItem устроило мне ад, потому что оно пыталось освободить 1-й экземпляр. Это вызвало [выпуск переменной], что привело к Exc_Bad_Access, потому что он указывал случайным образом (свободный указатель).

Чтобы решить эту проблему, просто объявите переменную1 как @private в файле .h.

Вот мой вопрос: я использовал "ленивые частные" переменные в течение достаточно долгого времени без каких-либо проблем, пока они не были задействованы в UINavigationController. Это ошибка в iPhone OS? Или с моей стороны есть фундаментальное непонимание цели C?


person Wayne Lo    schedule 11.05.2010    source источник


Ответы (2)


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

Другими словами, и myViewController_1stInstance, и myViewController_2ndInstance используют одну и ту же ячейку variable1 в памяти и перезаписывают друг друга.

Переменные, объявленные внутри фигурных скобок после вашего определения @interface, имеют место в памяти, выделенное средой выполнения для каждого экземпляра класса (каждый раз, когда вы вызываете [<ClassName> alloc]. Переменные, объявленные в глобальной области видимости (то есть вне каких-либо функций или объявлений классов) являются глобальными.Это означает, что переменная может содержать только одно значение для каждой запущенной копии вашего приложения.

В Objective-C нет действительно частных переменных, но вы можете скрыть их от других экземпляров во время компиляции, как описано здесь.

person Frank Schmitt    schedule 11.05.2010
comment
Я тоже об этом изначально догадывался. Но это было не так. - person Wayne Lo; 11.05.2010
comment
Даже если вы уверены, что статические переменные не вызывают проблемы, использовать статические переменные для данных для каждого экземпляра — плохая идея. Вот для чего нужны переменные-члены. - person Kristopher Johnson; 11.05.2010
comment
Они не статичны. Чтобы объявить статическую переменную, введите следующее: статическая переменная NSString1; - person Wayne Lo; 11.05.2010
comment
Любые переменные, объявленные вне функций/методов или определений классов, являются неявно статическими. - person Frank Schmitt; 11.05.2010
comment
Спасибо, Фрэнк. Это интересно и хорошее объяснение того, что я испытал. Я не уверен, почему Objective использует этот неявный стиль. Можете ли вы указать мне любую ссылку в Интернете по этому поводу? Как объявить не статическим? - person Wayne Lo; 11.05.2010
comment
@Frank Schmitt: Любые переменные, объявленные вне функций/методов или определений классов, неявно статичны, не так ли? Тогда что такое глобалы? - person Manjunath; 12.05.2010
comment
@Manjunath Вы правы в том, что правильный термин является глобальным, но под статическим я имею в виду, что они статически распределяются средой выполнения до запуска main, а не перегрузка термина языком C для обозначения одного экземпляра, локального для этого источника файл. - person Frank Schmitt; 12.05.2010

Немного запоздалая реакция, но я видел эту проблему раньше. Не нажимайте два анимированных viewControllers одновременно. Нажмите первый без анимации и нажмите второй с анимацией. UINavigationController не может обрабатывать две анимации одновременно.

person Steven    schedule 14.02.2012
comment
или вытащите первый без анимации и нажмите второй с анимацией. - person ChildhoodAndy; 15.10.2015