iOS MapKit拖动注释(MKAnnotationView)不再平移地图 [英] iOS MapKit dragged annotations (MKAnnotationView) no longer pan with map
问题描述
我正在学习在我初出茅庐的iOS应用程序中使用MapKit。我正在使用我的一些模型实体作为注释(将< MKAnnotation>
协议添加到其头文件中)。我还创建自定义MKAnnotationViews并将 draggable
属性设置为 YES
。
I'm learning to use MapKit in my fledgling iOS app. I'm using some of my model entities as annotations (added the <MKAnnotation>
protocol to their header file). I also create custom MKAnnotationViews and set the draggable
property to YES
.
我的模型对象有一个位置
属性,这是一个 CLLocation *
。为了符合< MKAnnotation>
协议,我在该对象中添加了以下内容:
My model object has a location
property, which is a CLLocation*
. To conform to the <MKAnnotation>
protocol, I added the following to that object:
- (CLLocationCoordinate2D) coordinate {
return self.location.coordinate;
}
- (void) setCoordinate:(CLLocationCoordinate2D)newCoordinate {
CLLocation* newLocation = [[CLLocation alloc]
initWithCoordinate: newCoordinate
altitude: self.location.altitude
horizontalAccuracy: self.location.horizontalAccuracy
verticalAccuracy: self.location.verticalAccuracy
timestamp: nil];
self.location = newLocation;
}
- (NSString*) title {
return self.name;
}
- (NSString*) subtitle {
return self.serialID;
}
所以,我有4个必需的方法。而且他们非常直截了当。当我在 MKAnnotationView
和 @draggable
属性中读取苹果文档时,它会显示以下内容:
So, I have the 4 required methods. And they're pretty straightforward. When I read the apple docs on MKAnnotationView
and the @draggable
property, it says the following:
将此属性设置为YES会使用户可以拖动注释。如果是,则关联的注释对象还必须实现setCoordinate:方法。此属性的默认值为NO。
Setting this property to YES makes an annotation draggable by the user. If YES, the associated annotation object must also implement the setCoordinate: method. The default value of this property is NO.
在其他地方, MKAnnotation
docs说:
And elsewhere, the MKAnnotation
docs say:
您对此属性的实现必须符合键值观察(KVO)。有关如何实现对KVO的支持的更多信息,请参阅键值观察编程指南。
Your implementation of this property must be key-value observing (KVO) compliant. For more information on how to implement support for KVO, see Key-Value Observing Programming Guide.
我已阅读(简要)文档,我根本不清楚我应该做些什么才能实现坐标
,这是我从 location
property本身就是一个合适的属性。
I have read that (brief) document, and it is not clear at all to me what I'm supposed to do to accomplish that so that the coordinate
, which I'm deriving from my location
property is a proper property in and of itself.
但我有理由相信它不能正常工作。当我拖动它时,它会移动,但是当我平移地图时它不再重新定位。
But I'm reasonably sure it's not working correctly. When I drag the pin, it moves, but then it no longer relocates when I pan the map.
更新
所以我试着玩MKPinAnnotationView股票。为此,我只是注释掉了我的委托的 mapView:viewForAnnotation:
方法。我发现默认情况下这些都不可拖动。我将 mapView:didAddAnnotationViews:
添加到我的委托,将添加的视图的 draggable
属性设置为是
。
So I tried playing with the stock MKPinAnnotationView. To do this, I simply commented out my delegate's mapView:viewForAnnotation:
method. I discovered that these aren't draggable by default. I added the mapView:didAddAnnotationViews:
to my delegate to set the draggable
property of the added views to YES
.
一旦这样配置,正如John Estropia在下面暗示的Pin视图似乎工作正常。我决定使用 mapView:annotationView:didChangeDragState:fromOldState:
委托钩子来仔细看看发生了什么:
Once configured thus, the Pin views, as hinted by John Estropia below, seem to work fine. I decided to use the mapView:annotationView:didChangeDragState:fromOldState:
delegate hook to get a closer look at what is going on:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState {
NSArray* states = @[@"None", @"Starting", @"Dragging", @"Cancelling", @"Ending"];
NSLog(@"dragStateChangeFrom: %@ to: %@", states[oldState], states[newState]);
}
对于库存引脚,会看到如下所示的日志输出:
For the stock pins, one will see log output that looks like this:
2014-02-05 09:07:45.924 myValve[1781:60b] dragStateChangeFrom: None to: Starting
2014-02-05 09:07:46.249 myValve[1781:60b] dragStateChangeFrom: Starting to: Dragging
2014-02-05 09:07:47.601 myValve[1781:60b] dragStateChangeFrom: Dragging to: Ending
2014-02-05 09:07:48.006 myValve[1781:60b] dragStateChangeFrom: Ending to: None
看起来很合乎逻辑。但是,如果切换到配置的 MKAnnotationView
,您将看到的输出如下:
Which looks pretty logical. But if you switch to the configured MKAnnotationView
, the output you will see looks like:
2014-02-05 09:09:41.389 myValve[1791:60b] dragStateChangeFrom: None to: Starting
2014-02-05 09:09:45.451 myValve[1791:60b] dragStateChangeFrom: Starting to: Ending
它错过了两次转换,从开始到拖动,从结束到无。
It misses TWO transitions, from Starting to Dragging, and from Ending to None.
所以我开始怀疑我需要做一些与属性不同的事情。但我仍然感到沮丧,为什么这不起作用。
So I begin to be skeptical that I need to do something different with properties. But I'm still frustrated with why this won't work.
更新2
我创建了自己的 Annotation
对象,以支持我的模型对象,它可以具有属性 coordinate
属性。行为保持不变。它似乎与 MKAnnotationView
有关。
I created my own Annotation
object to stand between my model objects, which could have a property coordinate
property. The behavior remains the same. It seems to be something with the MKAnnotationView
.
推荐答案
有很多有关如何使用委托方法的示例 mapView:viewForAnnotation:
显示设置 MKAnnotationView
。但是,仅仅因为您将 MKAnnotationView
实例的可拖动
属性设置为 YES
,您仍然需要编写一些代码来帮助它转换某些状态。 MapKit将负责将您的实例的 dragState
移动到 MKAnnotationViewDragStateStarting
和 MKAnnotationViewDragStateEnding
,但它不会执行其他转换。您可以在关于子类化 MKAnnotationView
的文档说明中看到这一点,并且需要覆盖`setDragState:animated:'
There are lots of examples about how to use the delegate method mapView:viewForAnnotation:
that show setting up an MKAnnotationView
. But what is not as obvious is that just because you set the draggable
property of your MKAnnotationView
instance to YES
, you still have to write some code to help it transition some of the states. MapKit will take care of moving your instance's dragState
to MKAnnotationViewDragStateStarting
and MKAnnotationViewDragStateEnding
, but it will not do the other transitions. You see hints of this in the docs notes about subclassing MKAnnotationView
and the need to override the `setDragState:animated:'
当拖动状态更改为MKAnnotationViewDragStateStarting时,将状态设置为MKAnnotationViewDragStateDragging。如果执行动画以指示拖动的开始,并且动画参数为YES,则在更改状态之前执行该动画。
When the drag state changes to MKAnnotationViewDragStateStarting, set the state to MKAnnotationViewDragStateDragging. If you perform an animation to indicate the beginning of a drag, and the animated parameter is YES, perform that animation before changing the state.
当状态更改为MKAnnotationViewDragStateCanceling时或MKAnnotationViewDragStateEnding,将状态设置为MKAnnotationViewDragStateNone。如果在拖动结束时执行动画,并且动画参数为YES,则应在更改状态之前执行该动画。
When the state changes to either MKAnnotationViewDragStateCanceling or MKAnnotationViewDragStateEnding, set the state to MKAnnotationViewDragStateNone. If you perform an animation at the end of a drag, and the animated parameter is YES, you should perform that animation before changing the state.
在这种情况下,我不是子类,但似乎 MKAnnotationView
仍然难以自己进行转换。所以你必须实现委托的 mapView:annotationView:didChangeDragState:fromOldState:
方法。例如
In this case, I'm not subclassing, but it seems that MKAnnotationView
still struggles to make the transitions on its own. So you have to implement the delegate's mapView:annotationView:didChangeDragState:fromOldState:
method. E.g.
- (void)mapView:(MKMapView *)mapView
annotationView:(MKAnnotationView *)annotationView
didChangeDragState:(MKAnnotationViewDragState)newState
fromOldState:(MKAnnotationViewDragState)oldState {
if (newState == MKAnnotationViewDragStateStarting) {
annotationView.dragState = MKAnnotationViewDragStateDragging;
}
else if (newState == MKAnnotationViewDragStateEnding || newState == MKAnnotationViewDragStateCanceling) {
annotationView.dragState = MKAnnotationViewDragStateNone;}
}
}
这样可以适当地完成任务,这样当您在拖动注释后平移地图时,注释会随着平移移动。
This allows things to complete appropriately, so that when you pan the map after dragging the annotation, the annotation moves with the pan.
这篇关于iOS MapKit拖动注释(MKAnnotationView)不再平移地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!