Почему у меня происходит сбой после освобождения MKMapView, если я его больше не использую?

У меня есть MKMapView. Иногда после того, как мой контроллер представления закрывается, я получаю EXC_BAD_ACCESS.

Я включил NSSZombies, и он выглядит как делегат MKMapView — мой контроллер представления! — вызывается, несмотря на освобождение подклассов MKMapView и UIViewController. Я проверил, и мое управление памятью правильное.

Что происходит?


person Steven Fisher    schedule 02.02.2010    source источник


Ответы (4)


Это из-за того, как работает MKMapView. Ожидается выполнение операции, поэтому MapKit сохраняет MKMapView и фактически еще не освободил его. Это само по себе не проблема. Проблема в том, что он все еще отправляет сообщения вашему делегату.

Обходной путь прост: как часть очистки вашего контроллера представления установите для делегата представления карты значение nil, что предотвратит отправку сообщений MKMapView ему.

Это задокументировано в Справочник по протоколу MKMapViewDelegate:

Перед выпуском объекта MKMapView, для которого вы установили делегата, не забудьте установить для свойства делегата этого объекта значение nil. Одно из мест, где вы можете сделать это, — это метод Dealloc, где вы избавляетесь от представления карты.

Редактировать: Дайте Оскару также проголосовать, чуть ниже, кто предоставил здесь цитату из документации.

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

person Steven Fisher    schedule 02.02.2010
comment
Большое вам спасибо за вашу помощь! - person Tuyen Nguyen; 27.04.2011
comment
Спасибо. Мой вопрос в том, должны ли мы как-то это знать. Если это ожидается от пользователей MapView, то почему бы нам не очистить указатель делегата от ВСЕХ элементов управления, которые принимают делегат? - person Oscar; 20.11.2011
comment
СПАСИБО! Это спасло мой день. - person Dominik Hadl; 18.03.2012

Хорошо, это подтверждение ответа. Это из документа Apple, но его нет в MKMapView. Его можно найти только в документации для его протокола делегата:

Перед выпуском объекта MKMapView, для которого вы установили делегата, не забудьте установить для свойства делегата этого объекта значение nil. Одно из мест, где вы можете сделать это, — это метод Dealloc, где вы избавляетесь от представления карты.

ПРИМЕЧАНИЕ. Это также относится к UIWebView.

Я установил указатель делегата MapView на nil в методе делегата Dealloc, и наши сбои, кажется, были устранены.

person Oscar    schedule 20.11.2011
comment
Я не знал, что Apple где-либо задокументировала это поведение. Спасибо; Я добавил ссылку в свой ответ (который также объясняет, почему). - person Steven Fisher; 29.11.2011

Установка делегата представления карты на nil у меня не сработала. Однако установка showsUserLocation=NO для делегата работала, гарантируя отсутствие обновлений местоположения.

person Dan Marinescu    schedule 02.09.2011
comment
У вас подключено представление карты? Я предполагаю, что это был ноль. - person Steven Fisher; 11.10.2011

Проблема в моем случае заключалась в том, что при первом запуске приложения я не нажимаю «разрешить» при запросе авторизации местоположения (случайно !!).

Удалив приложение и переустановив его, при появлении запроса я разрешаю авторизацию, и больше никаких сбоев!

person Luca Davanzo    schedule 21.05.2015