EDIT: изменил название. Я не знал этого в то время, но это дубликат Почему я падаю после освобождения MKMapView, если я больше не использую его?
Этот вопрос похож на Почему объект не деаллоцируется при использовании ARC + NSZombieEnabled, но отличается настолько, что я подумал, что его стоит выложить здесь, если кто-то понимает и может объяснить мне, что происходит. Другой вопрос может быть ошибкой XCode, поэтому я предполагаю, что это может быть похоже.
Сценарий:
RootViewController
имеет tableView
, отображающий кучу элементовdetailViewController
, содержащий другой tableView
detailViewController
содержит MKMapView
, показывающий местоположение элементаmapView. delegate = detailViewController
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, в котором вы избавляетесь от вид карты.