MKMapView все еще посылает сообщения делегату после того, как его супервью было деаллоцировано

EDIT: изменил название. Я не знал этого в то время, но это дубликат Почему я падаю после освобождения MKMapView, если я больше не использую его?


Этот вопрос похож на Почему объект не деаллоцируется при использовании ARC + NSZombieEnabled, но отличается настолько, что я подумал, что его стоит выложить здесь, если кто-то понимает и может объяснить мне, что происходит. Другой вопрос может быть ошибкой XCode, поэтому я предполагаю, что это может быть похоже.

Сценарий:

  1. RootViewController имеет tableView, отображающий кучу элементов
  2. При выборе ячейки появляется модальный detailViewController, содержащий другой tableView
  3. Одна из ячеек таблицы в detailViewController содержит MKMapView, показывающий местоположение элемента
  4. mapView. delegate = detailViewController
  5. Удаляем модальный detailViewController

Вскоре после этого приложение падает, поскольку MKMapView посылает mapView:viewForAnnotation: на теперь деаллоцированный detailViewController. Этот сбой произошел на пользовательском устройстве со сборкой специального дистрибутива, поэтому проблема не связана с NSZombieEnabled.

Я смог решить проблему, добавив:

_mapView.delegate = nil;

в метод dealloc метода tableViewCell, содержащего mapView.

ВОПРОС: почему необходимо обнулить делегат при деаллоцировании ячейки? Кажется, что mapView должен быть деаллоцирован ARC при деаллоцировании ячейки, что делает это ненужным. Хорошей практикой является обнуление делегатов, но я не думал, что это потребуется в данном случае.

EDIT: все вложенные виды как detailViewController, так и UITableViewCells объявлены как (nonatomic, strong) свойства ala:

@property (nonatomic, strong)   MKMapView *         mapView;

EDIT 2: Видимо, мне нужно лучше читать документацию. @fluchtpunkt прав. Вот соответствующая информация из MKMapView документации:

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

14
задан Community 23 May 2017 в 12:13
поделиться