IOS удаление наложений MKMapView не работает
Я хотел бы удалить все накладки моей карты в какой-то момент, и я пробовал разные способы, но он никогда не работает.
В прошлую попытку я сделал [self.mapView removeOverlays:self.mapView.overlays];
, и он все еще не работает. Любая идея, как я могу удалить эти оверлеи?
Спасибо.
ОБНОВЛЕНИЕ 1
У меня есть ошибка: malloc: *** error for object 0x5adc0c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Я думаю, что знаю почему, но не знаю, как это исправить...
Вот код, когда мне нужно нарисовать еще одну строку на моем mapView:
// Create a c array of points.
MKMapPoint *pointsArray = malloc(sizeof(CLLocationCoordinate2D) * 2);
// Create 2 points.
MKMapPoint startPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(oldLatitude, oldLongitude));
MKMapPoint endPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(newLatitude, newLongitude));
// Fill the array.
pointsArray[0] = startPoint;
pointsArray[1] = endPoint;
// Erase polyline and polyline view if not nil.
if (self.routeLine != nil) {
[_routeLine release];
self.routeLine = nil;
}
if (self.routeLineView != nil) {
[_routeLineView release];
self.routeLineView = nil;
}
// Create the polyline based on the array of points.
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
// Add overlay to map.
[self.mapView addOverlay:self.routeLine];
// clear the memory allocated earlier for the points.
free(pointsArray);
// Save old coordinates.
oldLatitude = newLatitude;
oldLongitude = newLongitude;
Итак, я освобождаю объект routeLine
, который является предыдущим наложением. Поэтому, когда я попытался удалить его, он сработает, потому что он уже освобожден.
Вот код делегата mapView для добавления оверлейных представлений:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKOverlayView* overlayView = nil;
if(overlay == _routeLine) {
// If we have not yet created an overlay view for this overlay, create it now.
if(self.routeLineView == nil) {
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:_routeLine] autorelease];
self.routeLineView.fillColor = [UIColor blueColor];
self.routeLineView.strokeColor = [UIColor blueColor];
// Size of the trace.
self.routeLineView.lineWidth = routeLineWidth;
}
overlayView = self.routeLineView;
}
return overlayView;
}
Если вы, ребята, знаете, как я могу исправить эту проблему, удалив все накладки из моего MKMapView, было бы замечательно!
ОБНОВЛЕНИЕ 2
Я попытался не выпускать объекты routeLine
и routeLineView
, и теперь он работает. Похоже, утечек нет. Итак, теперь я делаю это:
// Erase polyline and polyline view if not nil.
if (self.routeLine != nil) {
//[_routeLine release];
self.routeLine = nil;
}
if (self.routeLineView != nil) {
//[_routeLineView release];
self.routeLineView = nil;
}
Ответы
Ответ 1
Когда вы вызываете removeOverlays:
, на экране карты будут выпущены объекты MKOverlay и MKOverlayView.
Вы сохраняете свои собственные ссылки на них в _routeLine
и _routeLineView
.
После вызова removeOverlays:
ваши переменные будут указывать на уже выпущенную память. Когда вы повторно создаете полилинию, вы перевыпускаете, что приводит к сбою.
Поэтому удалите вызовы release
:
if (_routeLine != nil) {
[_routeLine release]; // <-- remove this
self.routeLine = nil;
}
if (_routeLineView != nil) {
[_routeLineView release]; // <-- remove this
self.routeLineView = nil;
}
Ответ 2
Когда вы выполняете код в отладчике, где появляется ошибка?
С одной мыслью, у вас может быть проблема с циклом сохранения/выпуска для self.routeLine
и self.routeLineView
. Предполагая, что они являются свойствами с атрибутом retain
, когда вы делаете
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
ваш синтезированный аксессуар сохраняет новый объект MKPolyline
. Этот объект также будет иметь пару сохранения/автозапуска из метода удобства, который его создал. Когда этот метод снова вызван, и вы вызываете
if (self.routeLine != nil) {
[_routeLine release];
self.routeLine = nil;
}
вы в конечном итоге освободите переменную дважды, сначала с явным вызовом [_routeLine release]
, а второй с синтезированным аксессором на вызове self.routeLine = nil;
. Он останется в памяти, но приведет к сбою приложения, когда ваш пул авторесурсов будет исчерпан.
В большинстве случаев, чтобы очистить все накладки на MKMapView
(с именем mapView
в этом примере), я сделал бы что-то вроде следующего:
for (id<MKOverlay> overlayToRemove in mapView.overlays)
{
if ([overlayToRemove isKindOfClass:[OverlayClassToRemove class]])
{
[mapView removeOverlay:overlayToRemove];
}
}
Ответ 3
Swift 3 extenstion
extension MKMapView
{
func removeAllOverlay(){
for overlay:MKOverlay in self.overlays {
self.remove(overlay)
}
}
}