Почему мой сбой и произнесение EXC-BAD_ACCESS при попытке показать GKPeerPickerController(ARC включен)

Недавно я столкнулся с проблемой в приложении, которое я разрабатываю. Приложение аварийно завершает работу с EXC_BAD_ACCESS. Это не имеет смысла, потому что автоматический подсчет ссылок включен.

В приложении у меня есть кнопка, которая связана с IBAction, который отображает GKPeerPickerController.

-(IBAction)showPicker:(id)sender
{
picker = [[GKPeerPickerController alloc ] init];
picker.delegate = self;
picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;

[picker show];
}

Это не имеет смысла, потому что, если я попытаюсь управлять памятью с помощью вызовов, таких как release, я получу сообщение об ошибке, в котором говорится, что ARC отключает этот вызов. Так что, насколько я знаю, я ничего не могу с этим поделать. Когда происходит сбой, EXC_BAD_ACCESS находится на линии, которая выделяет и инициализирует GKPeerPickerController.

1 ответ

Решение

Это происходит только во второй раз, когда вы пытаетесь запустить GKPeerPicker?

EXC_BAD_ACCESS генерируется, когда ваше приложение пытается получить доступ к области памяти, которой оно не "принадлежит". Это может происходить различными способами, даже с ARC, что затрудняет диагностику.

Проверьте этот вопрос, например, о сбое EXC_BAD_ACCESS (SIGSEGV) - использование NSZombies может быть способом отследить, что происходит.

Однако, немного больше понимания того, что происходит, может помочь вам понять этот сбой и исправить его.

Первый вопрос - как можно получить EXC_BAD_ACCESS, когда мы просто присваиваем недавно выделенный объект? Ну, вот тут-то и начинается волшебство ARC... Этот простой оператор присваивания назначает новый объект переменной экземпляра. Компилятор увидит это и скажет: "Ах... что у ivar уже может быть назначенный объект, и в этом случае я бы лучше выпустил его... Поэтому он добавит некоторый код для проверки nil и отпустите ivar, прежде чем он назначит новое значение.

Итак, я считаю маловероятным, что alloc / init вызывает вашу проблему, и более вероятно, что это то, что в данный момент хранится в вашем picker ivar... Что произойдет, если вы сделаете picker локальная переменная вместо ивара?

-(IBAction)showPicker:(id)sender
{
     GKPeerPickerController *localPicker = [[GKPeerPickerController alloc ] init];
     localPicker.delegate = self;
     localPicker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;

     [localPicker show];
}