问题描述
叠加层和 MapKit
似乎存在问题。与注释不同,叠加不会被重用,因此在添加多个叠加层时会导致实际设备出现内存问题。我多次遇到过这个问题。所以我的问题是,如何重用MKOverlay,从而提高 MapKit
上的叠加效果?
There seems to be an "issue" with overlays and the MapKit
. Unlike annotations, overlays aren't reused and therefore when adding multiple overlays would cause memory-problems on a real device. I've had this problem multiple times. So my question is, how can I reuse the MKOverlay and so improve the performance of overlays on MapKit
?
推荐答案
对此的回答不是重用,而是将它们全部绘制到一个 MKOverlayView
中,然后在地图上绘制。
The Answer to this is not "reusing" but to draw them all in to one MKOverlayView
and then draw that on the map.
多个 MKPolygons
, MKOverlays
等导致大量内存使用在地图上绘图时。这是由于 MapKit
不重复使用叠加层。由于注释具有 reuseWithIdentifier
,因此覆盖不会。每个叠加层在地图上创建一个新图层作为 MKOverlayView
,其中包含叠加层。通过这种方式,内存使用量将会快速增长,并且地图使用量会变得很慢......让我们说这种情况几乎不可能。
Multiple MKPolygons
, MKOverlays
etc. cause heavy memory-usage when drawing on the map. This is due the NOT reusing of overlays by MapKit
. As annotations have the reuseWithIdentifier
, overlays however don't. Each overlay creates a new layer as a MKOverlayView
on the map with the overlay in it. In that way memory-usage will rise quite fast and map-usage becomes... let's say sluggish to almost impossible.
因此有一种解决办法:而不是单独绘制每个叠加层,您可以将所有 MKOverlays
添加到一个 MKOverlayView
。这样你实际上只创建了一个 MKOverlayView
,因此无需重复使用。
Therefore there is a work-around: Instead of plotting each overlay individually, you can add all of the MKOverlays
to one MKOverlayView
. This way you're in fact creating only one MKOverlayView
and thus there's no need to reuse.
这是解决方法,在这种情况下为 MKPolygons
但对于其他人来说应该没有什么不同,例如 MKCircles
等。
This is the work-around, in this case for MKPolygons
but should be not very different for others like MKCircles
etc.
创建一个类: MultiPolygon
( NSObject的子类
)
in 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
in 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
现在创建一个类: MultiPolygonView
( MKOverlayPathView
的子类)
Now create a class: MultiPolygonView
(subclass of MKOverlayPathView
)
in 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
To us it import MultiPolygon.h
and MultiPolygonView.h
in your ViewController
从所有人创建一个多边形:
例如,我有一个包含多边形的数组: polygonsInArray
。
Create one polygon from all:As an example I've got an array with polygons: polygonsInArray
.
MultiPolygon *allPolygonsInOne = [[MultiPolygon alloc] initWithPolygons:polygonsInArray];
将allPolygonsInOne添加到mapView:
Add the allPolygonsInOne to the 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;
}
}
这大大减少了内存使用量 mapView
上的多个叠加层。您现在没有重复使用,因为只绘制了一个 OverlayView
。所以不需要重复使用。
And this greatly reduced memory usage for multiple overlays on the mapView
. You're not reusing now because only one OverlayView
is drawn. So no need to reuse.
这篇关于MKMapView具有多个叠加内存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!