«Нормальная» кнопка UIB вызывает исключение obj_stack_overflow или EXC_BAD_ACCESS - PullRequest
4 голосов
/ 14 сентября 2009

Это выглядит достаточно безобидно. В моем делегате приложения я проверяю NSUserDefaults на наличие флага, показывающего подсказки при запуске. Если он установлен, то в конце applicationDidFinishLaunching: я делаю это:

TipsViewController *vc = [[TipsViewController alloc]
  initWithNibName:@“TipsView" bundle:nil];
[window addSubview:vc.view];
[vc release];

Идея состоит в том, чтобы временно показать это представление. (Обратите внимание, что это не модальный VC. На данный момент нет контроллера навигации, плюс в любом случае в этом представлении нет панели навигации.)

Как только это представление будет отклонено, мы добавим наше окно с упрежденным UITabBarController к окну и перейдем к нему, затем удалим представление наконечника из главного окна. Я еще не дошел до точки увольнения, потому что, ну, продолжайте читать.

VC моего TipsView подключен примерно так:

UIView -> view -> File’s Owner (TipsViewController)
  UIImageView -> background image
  UIView -> tipView -> File’s Owner
    UIImageView -> background image
    UIScrollView
      UILabel (tip text)
    UIButton -> touch-up-inside -> -(IBAction)button1:
    UIButton -> touch-up-inside -> -(IBAction)button2:
    UIButton -> touch-up-inside -> -(IBAction)button3:

Источник содержит объявления и определения для всех трех IBAction вызовов. Прямо сейчас двое из них ничего не делают. Третий изменяет наконечник text, изменяет его размер, чтобы соответствовать, и регулирует представление contentSize прокрутки, чтобы соответствовать.

Когда я запускаю приложение, представление TipsViewController отображается очень хорошо. Я даже могу прокрутить текст подсказки. Тем не менее, когда я запускаю касание изнутри на любой UIButton , Xcode начинает сажать меня в источник (где я установил точку останова в каждой IBAction )… и затем выручает с EXC_BAD_ACCESS или obj_stack_overflow.

Я сравнил это с другими частями приложения, где у меня есть ВК, вид и кнопки. Он идентичен во всех отношениях, за исключением того, что в этом случае я добавил вид ВК в качестве подпредставления окна приложения вместо того, чтобы помещать ВК на контроллер навигации . Более того, в руководстве по программированию View Controller для iPhone OS сказано, что это честная игра:

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

Правда, у меня do есть UITabBarController , ожидающий своего часа, и в нем есть вкладки с UINavigationControllers (и другими VC). Однако, если отображается вид с подсказкой, представление контроллера панели вкладок имеет , а не , которое было добавлено в окно. Намерение состоит в том, чтобы заменить его после того, как мы закончили показывать советы. Другими словами, для всех намерений и целей мы временно действуем так, как будто у нас в игре есть один VC. После этого переключаемся на панель вкладок и сносим подсказку ВК.

Возможно, я делаю что-то не так? Есть ли способ лучше? («Должен быть лучший путь!»)

Пример трассировки стека:

#0  0x992b6f52 in objc_exception_throw
#1  0x302d6ffb in -[NSObject doesNotRecognizeSelector:]
#2  0x3026e056 in ___forwarding___
#3  0x3024a0a2 in __forwarding_prep_0___
#4  0x308f79d1 in -[UIApplication sendAction:to:from:forEvent:]
#5  0x309598b1 in -[UIControl sendAction:to:forEvent:]
#6  0x3095bad2 in -[UIControl(Internal) _sendActionsForEvents:withEvent:]
#7  0x3095a81e in -[UIControl touchesEnded:withEvent:]
#8  0x30910fdf in -[UIWindow _sendTouchesForEvent:]
#9  0x308faecb in -[UIApplication sendEvent:]
#10 0x309013e1 in _UIApplicationHandleEvent
#11 0x32046375 in PurpleEventCallback
#12 0x30245560 in CFRunLoopRunSpecific
#13 0x30244628 in CFRunLoopRunInMode
#14 0x32044c31 in GSEventRunModal
#15 0x32044cf6 in GSEventRun
#16 0x309021ee in UIApplicationMain
#17 0x00002888 in main at main.m:14

Как вы можете видеть из трассировки, мы в конечном итоге получим doesNotRecognizeSelector: ... за исключением того, что я ясно вижу методы в моем источнике VC для наконечника. Кроме того, они все подключены. (В IB нет многократных соединений или чего-то подобного. Там все выглядит хорошо, вплоть до отношений Владельца Файла.)

Подсказки приветствуются / приветствуются!

1 Ответ

8 голосов
/ 14 сентября 2009

Проблема тут же в вашем первом фрагменте кода: вы создаете экземпляр TipsViewController, сохраняете его представление, затем освобождаете контроллер представления - что приведет к его освобождению. Так что теперь target кнопок - это указатель на освобожденный контроллер представления.

Представление не сохраняет свой контроллер представления и не сохраняет своих делегатов или целей.

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

...