我想在MKMapView上进行叠加。因此,我创建了自定义对象:

@interface Spot : NSObject

@property int spot_id;
@property CLLocationCoordinate2D coordinate;
@property float radius;
@property NSObject<MKOverlay> * overlay;

- (id) initWithSpotId:(int)spot_id position:(CLLocationCoordinate2D)coordinate andRadius:(float)radius;

@end

有一个后端,可以不断更新Spots并将其传送到手机。所以我必须要:
  • 检查当前渲染的斑点是否仍然有效,还有
  • 如果是,它们是否移动或更改了半径?如果是这样,请更新它们(移动?/删除+重画?!)
  • 如果它们不再存在,请删除。

  • 有没有更好的方法来跟踪叠加层?在每个位置附加一个NSObject<MKoverlay> *参考并不断重新分配它对我来说有点奇怪。

    最佳答案

    似乎这里有三个问题:

  • 如何检测服务器中斑点的变化?

    这样做的丑陋方法是遍历您的位置,看看coordinate和/或radius是否已更改。更好的办法是让服务器更新创建,修改和删除时间戳或某些其他标识符,以便客户端能够检索自上次更新以来的所有创建,修改和/或删除。最好的方法是将其与某种形式的推送通知结合起来,这样也将主动向客户端通知这些更改。

    这个问题很难抽象地回答。这在很大程度上取决于服务器的功能和数据库的性质(例如,有多少个“地点”,它们多久更改一次,等等)。这不仅影响客户端-服务器体系结构,还影响客户端的实现。
  • 当地点改变时如何更新 map ?

    这是一个容易得多的问题。插入和删除都很容易。您只需要做addOverlay:(或在iOS 7中,就可以进行更新了,尽管更新不太好,但我认为最简单的方法是删除旧的覆盖层,然后重新添加回去,addOverlay:level:将为您处理用户界面。
  • removeOverlay:类的正确结构是什么?

    就像一个想法一样,但是拥有viewForOverlaySpot属性,然后再拥有coordinate对象似乎是重复的(因为这大概是具有相同两个属性的radius)。如果您的叠加层将成为id<MKOverlay> overlay对象,那么让MKCircle类本身符合MKCircle可能会更容易:
    @interface Spot : NSObject <MKOverlay>
    
    @property (nonatomic) int spot_id;
    @property (nonatomic) CLLocationCoordinate2D coordinate;
    @property (nonatomic) CLLocationDistance radius;
    @property (nonatomic, readonly) MKMapRect boundingMapRect;
    
    - (id) initWithSpotId:(int)spot_id position:(CLLocationCoordinate2D)coordinate andRadius:(CLLocationDistance)radius;
    
    @end
    

    然后,您所需要做的就是实现SpotMKOverlay:
    - (MKMapRect) boundingMapRect
    {
        MKMapPoint point = MKMapPointForCoordinate(self.coordinate);
        CLLocationDistance distance = self.radius * MKMetersPerMapPointAtLatitude(self.coordinate.latitude);
        MKMapRect rect = MKMapRectMake(point.x, point.y, distance * 2.0, distance * 2.0);
        rect = MKMapRectOffset(rect, -distance, -distance);
    
        return rect;
    }
    
    - (BOOL)intersectsMapRect:(MKMapRect)mapRect
    {
        return MKMapRectIntersectsRect(mapRect, [self boundingMapRect]);
    }
    

    您可能需要仔细检查boundingMapRect逻辑,但是我认为这是正确的。

    然后,您只需添加和删除intersectsMapRect对象即可覆盖自己。您所需要做的就是在boundingMapRect中实现Spot,例如,在7之前的iOS版本中,将是:
    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[Spot class]])
        {
            Spot *spot       = (id)overlay;
            MKCircle *circle = [MKCircle circleWithCenterCoordinate:spot.coordinate
                                                             radius:spot.radius];
    
            MKCircleView *overlayView = [[MKCircleView alloc] initWithCircle:circle];
            overlayView.fillColor     = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            overlayView.strokeColor   = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            overlayView.lineWidth     = 3.0;
            return overlayView;
        }
    
        return nil;
    }
    

    在iOS 7中,将为:
    - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[Spot class]])
        {
            Spot *spot       = (id)overlay;
            MKCircle *circle = [MKCircle circleWithCenterCoordinate:spot.coordinate
                                                             radius:spot.radius];
    
            MKCircleRenderer *renderer = [[MKCircleRenderer alloc] initWithCircle:circle];
            renderer.fillColor         = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            renderer.strokeColor       = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            renderer.lineWidth         = 3;
    
            return renderer;
        }
    
        return nil;
    }
    

    另一种方法是将viewForOverlay定义为:
    @interface Spot : NSObject <MKOverlay>
    
    @property (nonatomic) int spot_id;
    @property (nonatomic, strong) MKCircle *overlay;
    
    - (id) initWithSpotId:(int)spot_id position:(CLLocationCoordinate2D)coordinate andRadius:(CLLocationDistance)radius;
    

    然后,您可以只定义MKMapViewDelegate,然后SpotboundingMapRect返回适当的值(省去编写自己的代码):
    - (MKMapRect)boundingMapRect
    {
        return [self.circle boundingMapRect];
    }
    
    - (CLLocationCoordinate2D)coordinate
    {
        return [self.circle coordinate];
    }
    

    显然,coordinate方法将更改:
    - (id) initWithSpotId:(int)spot_id position:(CLLocationCoordinate2D)coordinate andRadius:(CLLocationDistance)radius;
    {
        self = [super init];
        if (self) {
            _spot_id = spot_id;
            _circle = [MKCircle circleWithCenterCoordinate:coordinate radius:radius];
        }
        return self;
    }
    

    就像MKCircle中的init(iOS 7.0之前的版本)一样:
    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[SpotCircle class]])
        {
            SpotCircle *spot = (id)overlay;
    
            MKCircleView *overlayView = [[MKCircleView alloc] initWithCircle:spot.circle];
            overlayView.fillColor     = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            overlayView.strokeColor   = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            overlayView.lineWidth     = 3.0;
    
            return overlayView;
        }
    
        return nil;
    }
    

    在iOS 7中,将为:
    - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[SpotCircle class]])
        {
            SpotCircle *spot = (id)overlay;
    
            MKCircleRenderer *renderer = [[MKCircleRenderer alloc] initWithCircle:spot.circle];
            renderer.fillColor         = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            renderer.strokeColor       = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            renderer.lineWidth         = 3;
    
            return renderer;
        }
    
        return nil;
    }
    

  • 希望对您有所帮助。

    关于ios - 在MKMapView上更新和组织叠加层,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16501587/

    10-12 00:11
    查看更多