Несколько MKOverlay на MKMapView приводят к предупреждениям памяти - PullRequest
6 голосов
/ 30 июля 2010

Я работаю над приложением для iPhone, которое показывает карту с несколькими круговыми наложениями в определенных местах.Я сталкиваюсь с серьезными проблемами с памятью и сбоями, когда я добавляю более 6 кругов и уменьшаю масштаб настолько, чтобы все они были видны.Когда я увеличиваю изображение так, что видны только 2 круга, все в порядке.Когда я удаляю MKOverlays, все работает нормально.

Кто-нибудь, кто распознает это поведение?

Код, который создает наложения.Я храню наложения в NSMutableDictionary для использования в будущем (чтобы иметь возможность удалить их с карты и предотвратить двойные наложения)

- (void)updateMarkersForZones:(NSArray *)zones {
    NSLog(@"MapViewController: Update Markers");
    // For each zone, show a marker
    for (Zone* zone in zones) {
        NSString *keyMarker = [NSString stringWithFormat:@"%d-marker", zone.id];

        MKCircle *circle = [overlayCache objectForKey:keyMarker];
        if (circle == nil) {
            // draw the radius circle for the marker
            double radius = MAX(zone.markerRadius * 1.0, 1.0);
            circle = [MKCircle circleWithCenterCoordinate:zone.location radius:radius];
            [mapView addOverlay:circle];
            // store the circle in a cache for future reference
            [overlayCache setObject:circle forKey:keyMarker];
        }
    }
}

Код, который делает представления наложения

#pragma mark -
#pragma mark MKMapViewDelegate
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay{
     MKCircleView *circleView = [[[MKCircleView alloc] initWithCircle:overlay] autorelease];
    circleView.lineWidth = 1.0;
    circleView.strokeColor = [UIColor redColor];
    return circleView;
}

Код, который освобождает оверлейный кеш

- (void)dealloc {
    [overlayCache release];
    [mapView release];
    [super dealloc];
}

1 Ответ

6 голосов
/ 02 августа 2010

Я вижу, как происходит то же самое.Я рисую MKPolylines вместо кругов, но у меня точно такая же проблема.1 строка работает нормально, но когда я начинаю добавлять несколько и пытаться переместить карту вокруг нее, происходит сбой с предупреждениями памяти.Я вставил бы мой код, но он в значительной степени идентичен вышеуказанному изменяющемуся кругу для строки.

РЕДАКТИРОВАТЬ: похоже, проблема в том, что каждый оверлей создает новый основной слой анимации.здесь есть обходной путь - https://devforums.apple.com/thread/48154?tstart=0 Также я считаю, что это известная ошибка, которая должна быть исправлена ​​в следующем выпуске

РЕДАКТИРОВАТЬ: обходной путь - "Это не проблема с APIа скорее реализация. Мое предложение вручную объединить их в одну - это временное решение.

Например, вот как вы можете реализовать MultiPolygon и соответствующее представление: "

    @interface MultiPolygon : NSObject <MKOverlay> {
    NSArray *_polygons;
    MKMapRect _boundingMapRect;
}

- (id)initWithPolygons:(NSArray *)polygons;
@property (nonatomic, readonly) NSArray *polygons;

@end

@implementation MultiPolygon

@synthesize polygons = _polygons;

- (id)initWithPolygons:(NSArray *)polygons
{
    if (self = [super init]) {
        _polygons = [polygons copy];

        NSUInteger polyCount = [_polygons count];
        if (polyCount) {
            _boundingMapRect = [[_polygons objectAtIndex:0] boundingMapRect];
            NSUInteger i;
            for (i = 1; i < polyCount; i++) {
                _boundingMapRect = MKMapRectUnion(_boundingMapRect, [[_polygons objectAtIndex:i] boundingMapRect]);
            }
        }
    }
    return self;
}

- (void)dealloc
{
    [_polygons release];
    [super dealloc];
}

- (MKMapRect)boundingMapRect
{
    return _boundingMapRect;
}

- (CLLocationCoordinate2D)coordinate
{
    return MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMidX(_boundingMapRect), MKMapRectGetMidY(_boundingMapRect)));
}

@end



@implementation MultiPolygonView

- (CGPathRef)polyPath:(MKPolygon *)polygon
{
    MKMapPoint *points = [polygon points];
    NSUInteger pointCount = [polygon pointCount];
    NSUInteger i;

    if (pointCount < 3)
        return NULL;

    CGMutablePathRef path = CGPathCreateMutable();

    for (MKPolygon *interiorPolygon in polygon.interiorPolygons) {
        CGPathRef interiorPath = [self polyPath:interiorPolygon];
        CGPathAddPath(path, NULL, interiorPath);
        CGPathRelease(interiorPath);
    }

    CGPoint relativePoint = [self pointForMapPoint:points[0]];
    CGPathMoveToPoint(path, NULL, relativePoint.x, relativePoint.y);
    for (i = 1; i < pointCount; i++) {
        relativePoint = [self pointForMapPoint:points[i]];
        CGPathAddLineToPoint(path, NULL, relativePoint.x, relativePoint.y);
    }

    return path;
}

- (void)drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)context
{
    MultiPolygon *multiPolygon = (MultiPolygon *)self.overlay;
    for (MKPolygon *polygon in multiPolygon.polygons) {
        CGPathRef path = [self polyPath:polygon];
        if (path) {
            [self applyFillPropertiesToContext:context atZoomScale:zoomScale];
            CGContextBeginPath(context);
            CGContextAddPath(context, path);
            CGContextDrawPath(context, kCGPathEOFill);
            [self applyStrokePropertiesToContext:context atZoomScale:zoomScale];
            CGContextBeginPath(context);
            CGContextAddPath(context, path);
            CGContextStrokePath(context);
            CGPathRelease(path);
        }
    }
}

@end
...