MKMapView具有多个叠加内存问题

wkb*_*erg 5 memory mkmapview ios mkoverlay mkpolygon

似乎有一个覆盖和"问题" MapKit.与注释不同,叠加层不会被重用,因此在添加多个叠加层时会导致真实设备出现内存问题.我多次遇到过这个问题.所以我的问题是,我如何重用MKOverlay,从而提高叠加的性能MapKit

wkb*_*erg 13

答案不是"重复使用",而是将它们全部绘制成一个MKOverlayView然后在地图上绘制.

在地图上绘图时MKPolygons,多个MKOverlays等会导致大量内存使用.这是因为没有重复使用叠加MapKit.reuseWithIdentifier然而,正如注释所示,覆盖不会.每个叠加层都会MKOverlayView在地图上创建一个新图层,其中包含叠加层.通过这种方式,内存使用量将会快速增长,并且地图使用会变得......让我们说这种情况几乎不可能.

因此,有一种解决方法:您可以将所有的叠加添加MKOverlays到一个,而不是单独绘制每个叠加层MKOverlayView.这样你实际上只创建一个MKOverlayView,因此不需要重复使用.

这是解决方法,在这种情况下,MKPolygons但对于其他类似的应该没有很大的不同MKCircles.

创建一个类:( MultiPolygon子类NSObject)

MultiPolygon.h:

#import <MapKit/MapKit.h> //Add import MapKit

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

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

@end
Run Code Online (Sandbox Code Playgroud)

MultiPolygon.m:

@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;
}

- (MKMapRect)boundingMapRect
{
 return _boundingMapRect;
}

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

@end
Run Code Online (Sandbox Code Playgroud)

现在创建一个类:( MultiPolygonView子类MKOverlayPathView)

MultiPolygonView.h:

#import <MapKit/MapKit.h>

@interface MultiPolygonView : MKOverlayPathView

@end
Run Code Online (Sandbox Code Playgroud)

MultiPolygonView.m:

#import "MultiPolygon.h"  //Add import "MultiPolygon.h"


@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
Run Code Online (Sandbox Code Playgroud)

对我们来说,它导入MultiPolygon.hMultiPolygonView.h在ViewController中

从all创建一个多边形:作为一个例子,我有一个带有多边形的数组:polygonsInArray.

MultiPolygon *allPolygonsInOne = [[MultiPolygon alloc] initWithPolygons:polygonsInArray];
Run Code Online (Sandbox Code Playgroud)

将allPolygonsInOne添加到mapView:

[mapView addOverlay:allPolygonsInOne];
Run Code Online (Sandbox Code Playgroud)

还要更改viewForOverlay方法:

-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{

 if ([overlay isKindOfClass:[MultiPolygon class]]) {
     MultiPolygonView *polygonsView = [[MultiPolygonView alloc] initWithOverlay:(MultiPolygon*)overlay];
     polygonsView.fillColor = [[UIColor magentaColor] colorWithAlphaComponent:0.8];
     polygonsView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.8];
     polygonsView.lineWidth = 1;
     return polygonsView;
 }
 else {
   return nil;
 }

}
Run Code Online (Sandbox Code Playgroud)

这大大减少了多个叠加层的内存使用量mapView.你现在没有重复使用,因为只OverlayView画了一个.所以不需要重复使用.

  • 我会建议 - "github it". (3认同)