Я просмотрел другие отчеты по этому вопросу, и, похоже, ни один из них не подходит. Наше приложение наносит вред частым (но не надежно воспроизводимым) сбоям, подобным этому:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x333a6c98 objc_msgSend + 16
1 MapKit 0x30be52fc -[MKMapView annotationContainer:viewForAnnotation:] + 36
2 MapKit 0x30be4f8e -[MKAnnotationContainerView _addViewForAnnotation:] + 270
3 MapKit 0x30c0f164 -[MKAnnotationContainerView addViewForManagedAnnotation:notifyDelegate:] + 12
4 MapKit 0x30c0b874 -[MKMapView(UserPositioningInternal) _runPositioningChange] + 1036
5 MapKit 0x30c09a86 -[MKMapView(UserPositioningInternal) _startPositioningChange:] + 22
6 MapKit 0x30c0d04a -[MKMapView(UserPositioningInternal) locationManagerUpdatedLocation:] + 578
7 CoreFoundation 0x360bcefc -[NSObject(NSObject) performSelector:withObject:] + 16
8 CoreFoundation 0x360fa2f2 -[NSArray makeObjectsPerformSelector:withObject:] + 394
9 MapKit 0x30bfc802 -[MKLocationManager _reportLocationStatus:] + 34
10 MapKit 0x30bfdd6c -[MKLocationManager _reportLocationSuccess] + 36
11 MapKit 0x30bfd9c6 -[MKLocationManager locationManager:didUpdateToLocation:fromLocation:] + 674
Сообщения об этом часто появляются в Интернете, но многие, похоже, остаются нерешенными. Я не делаю ничего сумасшедшего, просто показываю положение пользователя и один маркер на карте. Я следовал за примерами, которые мог найти, и посмотрел код для глупостей, но не смог найти ни одного.
Вот как мой делегат MapView обрабатывает viewForAnnotation:
- (MKAnnotationView*)mapView:(MKMapView*)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// If it's the user location, just return nil.
if([annotation isKindOfClass:[MKUserLocation class]])
{
return nil; // Use default system user-location view.
}
else
{
// Try to dequeue an existing pin view first.
MKPinAnnotationView* pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"stashMarkerID"];
if(!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:@"stashMarkerID"] autorelease];
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.animatesDrop = YES;
pinView.canShowCallout = NO;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
}
Похоже, что сбой связан с изменением местоположения пользователя, но как только маркер местоположения пользователя добавлен, я не связываюсь с ним. Когда мне нужно обновить еще один маркер карты, я пропускаю пользовательский маркер при удалении другого:
// Add the marker to the map.
// Remove old one(s) first.
int i = 0;
while(i < [mapView.annotations count])
{
if ([[mapView.annotations objectAtIndex:i] isKindOfClass:[StashMarker class]])
{
[mapView removeAnnotation:[mapView.annotations objectAtIndex:i]];
}
else
{
i++;
}
}
Делегат является контроллером для всего экрана, поэтому он не освобождается; сбой происходит, когда экран вверх. Не то, чтобы это имело значение, но отображение карты выглядит так:
Любые догадки или идеи будут высоко оценены! Это на iOS 5.0.1.
ОБНОВЛЕНИЕ: Мы обнаружили, что этот сбой происходит, когда MKMapView вообще не должно существовать. Представление, содержащее это, уже давно появилось. Интересно, если мы столкнулись с проблемой, о которой сообщалось здесь: MKMapView аварийно завершает работу приложения, когда контроллер представления отключен
ОБНОВЛЕНИЕ 2: Вот еще один отчет по существу того же самого вопроса: Почему у меня происходит сбой после освобождения MKMapView, если я больше его не использую?
Это кажется необычно грязным для Какао, когда необходимо установить для делегата MKMapView значение nil после того, как мы ожидаем, что MapView будет освобожден. В таком случае, почему мы не должны делать это для всех элементов управления, которые принимают делегата?