EXC_BAD_ACCESS с IBACTION

Я много читал об этой проблеме, но мой все еще кажется каким-то другим. Итак, насколько я понял, EXC_BAD_ACCESS возникает при проблемах с управлением памятью.

Дело в том, что моего там вроде (! :)) нет. Дело в том, что я просто добавил кнопку в IB, закругленный прямоугольник, без изображения. Я подключил его с помощью IBACTION, который я определил в своем классе. Кстати, этот метод ничего не делает (!).

В любом случае, как только я нажимаю кнопку, приложение вылетает с ошибкой «EXC_BAD_ACCESS».

Насколько я вижу, я точно ничего не перевыпускаю. Что не так?

Любые подсказки?

Это мой журнал консоли:

Loading program into debugger…
sharedlibrary apply-load-rules all
Program loaded.
target remote-mobile /tmp/.XcodeGDBRemote-148-79
Switching to remote-macosx protocol
mem 0x1000 0x3fffffff cache
mem 0x40000000 0xffffffff none
mem 0x00000000 0x0fff none
run
Running…
[Switching to thread 11779]
[Switching to thread 11779]
(gdb) continue
2010-01-15 09:16:34.800 FlightControl1[1899:207] Table loaded
2010-01-15 09:16:35.200 FlightControl1[1899:207] 23
2010-01-15 09:16:35.350 FlightControl1[1899:207] debug
Program received signal:  “EXC_BAD_ACCESS”.
(gdb) 

Это то, что я получаю после того, как я поднялся по стеку:

#0  0x31ec3ebc in objc_msgSend ()
#1  0x33605784 in -[UIApplication sendAction:to:from:forEvent:] ()
#2  0x336056ec in -[UIApplication sendAction:toTarget:fromSender:forEvent:] ()
#3  0x336056b4 in -[UIControl sendAction:to:forEvent:] ()
#4  0x3360530c in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#5  0x33605f8c in -[UIControl touchesEnded:withEvent:] ()
#6  0x335fd9ac in _UIGestureRecognizerUpdateObserver ()
#7  0x30da1830 in __CFRunLoopDoObservers ()
#8  0x30de9346 in CFRunLoopRunSpecific ()
#9  0x30de8c1e in CFRunLoopRunInMode ()
#10 0x332e7374 in GSEventRunModal ()
#11 0x335adc30 in -[UIApplication _run] ()
#12 0x335ac230 in UIApplicationMain ()
#13 0x000027a8 in main (argc=1, argv=0x2ffff4d8) at /Users/SomePath/main.m:14

person Icky    schedule 15.01.2010    source источник
comment
вы можете вставить в журнал консоли, пожалуйста?   -  person Sam Jarman    schedule 15.01.2010
comment
обратите также внимание, что IBACTION сам по себе является не чем иным, как заполнителем, который IB может использовать для поиска предметов. посмотрите на код после предварительной обработки, IBACTIONs не существует   -  person KevinDTimm    schedule 15.01.2010
comment
Я добавил свой журнал консоли в вопрос. @kevin: Честно говоря, я не уверен, что с этим делать.   -  person Icky    schedule 15.01.2010
comment
Скорее всего, объект, который выполняет действие кнопки, уже был освобожден до того, как вы нажмете кнопку. Вы можете попробовать добавить вызов NSLog в его -dealloc и его метод действия кнопки, чтобы проверить это. Также может помочь включение точек останова для objc_exception_throw и -[_NSZombie methodSignatureForSelector:] (и включение NSZombies).   -  person Costique    schedule 15.01.2010
comment
@ приглашение (gdb), введите команду «назад». Это покажет трассировку стека того, что происходило до вашей ошибки. Простой первый шаг к определению места возникновения ошибки.   -  person KevinDTimm    schedule 15.01.2010
comment
Хорошо, я попробую последнее. НО, просто чтобы помочь мне понять: теперь у меня есть версия, в которой я не отпускаю экземпляр кнопки, который я создал программно до сих пор. Раньше у меня был такой, который я создал в IB. Как это возможно, что его нет?   -  person Icky    schedule 15.01.2010
comment
Хорошо, я попробовал последнее - см. выше. TBH, я этого не понимаю.   -  person Icky    schedule 15.01.2010
comment
Сбой в objc_msgSend() чаще всего означает, что сообщение было отправлено освобожденному объекту. В вашем случае я подозреваю, что это объект, связанный с вашим действием кнопки. Это контроллер представления? Можете ли вы убедиться, что он все еще существует, когда вы нажимаете кнопку?   -  person Costique    schedule 15.01.2010
comment
Ну вот и все, Костик! Я совершенно не думал об этом, так как все остальное в контроллере работало нормально. Я имею в виду, я все еще мог прокручивать, использовать что-то странное. Похоже, мне нужно снова сделать руководство по управлению памятью...   -  person Icky    schedule 15.01.2010


Ответы (3)


Меня это тоже мучило несколько часов. Как и ожидалось, проблема с памятью. Контроллер, выступающий в качестве цели для кнопки, был освобожден. Это был корневой контроллер навигационного контроллера, представление которого добавлялось непосредственно в окно. Мой код выглядел так:

MyController *myController = [[MyController new] autorelease];
UINavigationController* navController = 
    [[[UINavigationController alloc] initWithRootViewController:myController] autorelease];
[window addSubview:navController.view];

Я предполагал, что myController будет сохранен, когда он будет передан в качестве корневого контроллера UINavigationController, но это оказалось неверным. Решение состояло в том, чтобы назначить контроллер локальной переменной и освободить его в dealloc. Интерфейс объекта, содержащего приведенный выше код, должен иметь:

...
@property (retain, nonatomic) MyController *myController;
...

И реализация:

self.myController = [[MyController new] autorelease];
UINavigationController* navController = 
    [[[UINavigationController alloc] initWithRootViewController:myController] autorelease];
[window addSubview:navController.view];

...

- (void)dealloc {
    [self.myController release];
    ...
    [super dealloc];
}
person gammal    schedule 24.02.2010
comment
СПАСИБО! initWithRootViewController, не сохраняющий корневой вид, — это сумасшествие. - person esbenr; 03.07.2012
comment
Вы представляете навигационный контроллер сразу после его выделения? - person ıɾuǝʞ; 28.08.2012
comment
У меня тоже была эта проблема при использовании ARC. Проблема заключалась в том, что я создавал экземпляр контроллера представления из метода var. Просто сделайте его экземпляром var или свойством. - person Jorge; 19.12.2012
comment
Отладчик показывает, что initWithRootViewController дважды сохраняет контроллер. - person Haitao Li; 26.02.2013
comment
то же самое, спасатель! Я использую ARC Как только я увидел этот пост и понял, что происходит, я добавил -(void) Dealloc с точкой останова в класс, где я добавил свою кнопку, и я мог точно видеть, где вызывается релиз. - person Tinkerbell; 12.03.2015

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

Если вы инициируете контроллер следующим образом:

MyController* controller = [[MyController alloc] initWithNibName:@"MyNib" bundle:nil];
[self.view addSubview:controller.view];

Все будет в порядке, если вы не используете ARC, поскольку ссылка не будет освобождена до тех пор, пока она не будет освобождена вручную. Поэтому у меня возникла эта проблема при обновлении проектов для использования ARC.

Если вы инициируете контроллер как автоосвобождение или используете ARC, то, как только область, в которой существует контроллер, заканчивается, сборщик мусора освободит контроллер, а события нажатия кнопки вызовут исключения с плохой памятью.

Способ решить эту проблему состоит в том, чтобы сохранить ссылку активной, поэтому объявите ее в интерфейсе или если для нее требуется внешний доступ в качестве свойства.

@interface MyParentController : UIView {
@private
    MyController* controller;
}

Затем добавьте его как:

controller = [[MyController alloc] initWithNibName:@"MyNib" bundle:nil];
[self.view addSubview:controller.view];

Если вы хотите, чтобы память собиралась позже, просто установите значение nil.

person OnlyJoe    schedule 17.03.2013

У меня есть мысль. Это случилось со мной много лет назад. В IB ваше свойство View подключено к вашему представлению?

Я однажды отцепил их, и приложение так и не запустилось.

Кстати, чем хуже, тем лучше, начните проект заново. Не стоит этих головных болей, если вы уже проделали 2 минуты работы.

Добро пожаловать в мир программирования для iPhone. Вам может понадобиться один из них довольно скоро wigsmen.com ;-)

person Sam Jarman    schedule 15.01.2010