MKMapView具有多个叠加内存问题 [英] MKMapView with multiple overlays memory-issue

查看:119
本文介绍了MKMapView具有多个叠加内存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

叠加层和 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具有多个叠加内存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆