MKMapView有多个覆盖内存的问题
似乎有一个覆盖和MapKit
的“问题”。 与注释不同的是,叠加层不会被重用,因此添加多个叠加层会导致真实设备上的内存问题。 我有这个问题多次。 所以我的问题是,如何重新使用MKOverlay,从而提高MapKit
覆盖层的性能?
对此的回答不是“重用”,而是将它们全部绘制到一个MKOverlayView
,然后在地图上绘制。
在地图上绘制时,多个MKPolygons
, MKOverlays
等会导致大量的内存使用。 这是由于MapKit
没有重用覆盖。 由于注释具有reuseWithIdentifier
,所以叠加不会。 每个叠加层MKOverlayView
在地图上以覆盖graphics式创build一个新的图层,作为MKOverlayView
。 以这种方式,内存使用率将会上升得相当快,地图使用变成了……让我们说呆滞到几乎不可能。
因此,有一个解决方法:您可以将所有MKOverlays
添加到一个MKOverlayView
,而不是单独绘制每个覆盖MKOverlayView
。 这样你实际上只创build一个MKOverlayView
,因此不需要重用。
这是MKPolygons
的解决方法,但对MKCircles
等其他人应该没什么不同。
创build一个类: 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
在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
现在创build一个类: MultiPolygonView
( MKOverlayPathView
子类)
在MultiPolygonView.h
:
#import <MapKit/MapKit.h> @interface MultiPolygonView : MKOverlayPathView @end
在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
对我们来说,在您的ViewController中导入MultiPolygon.h
和MultiPolygonView.h
从全部创build一个多边形:作为一个例子,我有一个多边形数组: polygonsInArray
。
MultiPolygon *allPolygonsInOne = [[MultiPolygon alloc] initWithPolygons:polygonsInArray];
将allPolygonsInOne添加到mapView:
[mapView addOverlay:allPolygonsInOne];
还要改变你的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; } }
这大大减less了mapView
上多个叠加层的内存使用量。 您现在没有重用,因为只绘制了一个OverlayView
。 所以不需要重复使用。