我想在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
是否已更改。更好的办法是让服务器更新创建,修改和删除时间戳或某些其他标识符,以便客户端能够检索自上次更新以来的所有创建,修改和/或删除。最好的方法是将其与某种形式的推送通知结合起来,这样也将主动向客户端通知这些更改。这个问题很难抽象地回答。这在很大程度上取决于服务器的功能和数据库的性质(例如,有多少个“地点”,它们多久更改一次,等等)。这不仅影响客户端-服务器体系结构,还影响客户端的实现。
这是一个容易得多的问题。插入和删除都很容易。您只需要做
addOverlay:
(或在iOS 7中,就可以进行更新了,尽管更新不太好,但我认为最简单的方法是删除旧的覆盖层,然后重新添加回去,addOverlay:level:
将为您处理用户界面。removeOverlay:
类的正确结构是什么?就像一个想法一样,但是拥有
viewForOverlay
和Spot
属性,然后再拥有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
然后,您所需要做的就是实现
Spot
和MKOverlay
:- (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
,然后Spot
从boundingMapRect
返回适当的值(省去编写自己的代码):- (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/