MKAnnotation Pin 不会拖动,即使设置为可拖动

Posted

技术标签:

【中文标题】MKAnnotation Pin 不会拖动,即使设置为可拖动【英文标题】:MKAnnotation Pin won't drag, even though set as draggable 【发布时间】:2015-07-13 07:37:43 【问题描述】:

多年来,我一直试图在地图视图上放置可拖动的注释。 (我使用的是默认图钉,而不是我自己的图钉)到目前为止,我只能在设定的坐标处显示它(真的不是什么成就),我需要首先获取注释才能对被选中做出反应,它没有永远不会被didChangeDragState func 接收。然后我需要能够拖动它,将其放置在新位置并获取新位置的坐标。

我对 Swift 相当陌生,但我接手了一个相当困难的项目。 我已经查看了我在谷歌上找到的几乎所有东西,寻找“可拖动的MKAnnotation Swift 中的 mapkit”和类似的变体。(编辑:我没有找到任何可以阐明我的问题的答案,其中所有其他答案给出了如何上传个性化MKAnnotation的回复。他们都有标题字段,但没有一个答案提到标题字段是必要的,结果证明这是主要问题。他们只提到我应该设置dragState 来控制 pin 的移动,但在我的情况下这是不正确的,如下所示) 无论如何! 下面是我尝试实现 mapView 并添加注释的代码。

var currentLat:CLLocationDegrees!
var currentLong:CLLocationDegrees!
var currentCoordinate:CLLocationCoordinate2D! 
....
override func viewDidAppear(animated: Bool) 
    let annotation = PinAnnotationClass()
    annotation.setCoordinate(currentCoordinate)
    //annotation.setCoordinate(currentCoordinate)
    //AnnotationView()
    self.mapView.addAnnotation(annotation)


override func viewDidLoad() 
    super.viewDidLoad()
    println("hello!")
    self.mapView.delegate = self
    loadMap()

    findPath()


func loadMap()

    currentCoordinate = CLLocationCoordinate2DMake(currentLat, currentLong)
    var mapSpan = MKCoordinateSpanMake(0.01, 0.01)
    var mapRegion = MKCoordinateRegionMake(currentCoordinate, mapSpan)
    self.mapView.setRegion(mapRegion, animated: true)

连同扩展名:

extension DetailsViewController: MKMapViewDelegate     
func mapView(mapView: MKMapView!,
    viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! 

        if annotation is MKUserLocation 
            //return nil so map view draws "blue dot" for standard user location
            return nil
        
            let reuseId = "pin"

            var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
            if pinView == nil 
                pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
                pinView!.canShowCallout = true
                pinView!.draggable = true
                pinView!.annotation.coordinate
                pinView!.animatesDrop = true
                pinView!.pinColor = .Green
            
            else 
                pinView!.annotation = annotation
            

            return pinView


  func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) 
    if (newState == MKAnnotationViewDragState.Starting) 
        view.dragState = MKAnnotationViewDragState.Dragging
     else if (newState == MKAnnotationViewDragState.Ending || newState == MKAnnotationViewDragState.Canceling)
        view.dragState = MKAnnotationViewDragState.None
    


func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) 
    if let annotation = view.annotation as? PinAnnotationClass
    

我还有一个自定义 PinAnnotation 类:

import Foundation
import MapKit

class PinAnnotationClass : NSObject, MKAnnotation 
private var coord: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 0, longitude: 0)

var coordinate: CLLocationCoordinate2D 
    get 
        return coord
    


var title: String = ""
var subtitle: String = ""

func setCoordinate(newCoordinate: CLLocationCoordinate2D) 
    self.coord = newCoordinate

【问题讨论】:

ios Swift MapKit making an annotation draggable by the user? 的可能重复项 我以为我遇到了同样的问题,但事实证明我只是没有在正确的位置进行拖动。看起来拖动的位置非常有限(销的底部 - 不是销头)。 【参考方案1】:

最初的问题是注解的title没有设置。

如果注释的title 未设置,则无法将其设置为“已选择”状态,并且不会显示标注,didSelectAnnotationView 也不会被调用。

由于要拖动注解,必须先选择它,如果没有设置title,你将无法拖动它。

所以在创建注解时,将其title 设置为:

let annotation = PinAnnotationClass()
annotation.title = "hello"
annotation.setCoordinate(currentCoordinate)

这至少应该让您开始拖动它,但由于您使用的是MKPinAnnotationView 而不是普通的MKAnnotationView,您确实不需要需要实现didChangeDragState。其实在使用MKPinAnnotationView的时候如果真的实现了,注解就不会正常拖动了。

didChangeDragState 中,删除设置view.dragState 的代码——使用MKPinAnnotationView 时不需要它。

相反,您可以只记录注释被删除的坐标:

func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) 

    if newState == MKAnnotationViewDragState.Ending 
        let ann = view.annotation
        print("annotation dropped at: \(ann!.coordinate.latitude),\(ann!.coordinate.longitude)")
    


不相关,但PinAnnotationClass 实现比它需要的更复杂。您不需要为coordinate 编写显式的get 和set 方法。只需声明coordinate,getter/setter 就会为您完成:
class PinAnnotationClass : NSObject, MKAnnotation 
    var title: String = ""
    var subtitle: String = ""
    var coordinate: CLLocationCoordinate2D = kCLLocationCoordinate2DInvalid
    //kCLLocationCoordinate2DInvalid is a pre-defined constant
    //better than using "0,0" which are technically valid

您还需要更改坐标的分配方式:

//annotation.setCoordinate(currentCoordinate)  //old
annotation.coordinate = currentCoordinate      //new


最后,也无关,但viewForAnnotation 中的这一行
pinView!.annotation.coordinate

意味着什么,什么都不做,删除它。

【讨论】:

嗨,安娜,非常感谢!我在其他帖子上看到过你的cmets,你太棒了!我应该编辑上面的帖子以反映您的更改,还是应该让有类似问题的人看到我的问题然后看到您的答案? 谢谢,请留下原始代码作为参考。如果问题中的代码被更改,答案看起来很奇怪(因为现在代码已经“工作”了)。接受答案表明更改对您有用。但是,如果您愿意,您可以将更新后的代码添加到您的帖子中,同时显示“之前”和“之后”,但通常不会这样做。 附注...PinAnnotationClass 中的coordinate 属性必须是var。就我而言,我将其声明为let coordinate,但直到我将其更改为var,它才起作用。 @Anna 谢谢,效果很好,拔掉了我的一些头发,直到我找到了这个 :) 再次感谢

以上是关于MKAnnotation Pin 不会拖动,即使设置为可拖动的主要内容,如果未能解决你的问题,请参考以下文章

在实现 MKAnnotation 时如何获取 pin 的标题和副标题?

iPhone:MKAnnotation Pin 颜色“选定状态”

如何将 MKAnnotation Pin 一个一个丢掉?

拖动 MKPinAnnotationView 抛出错误

拖动我的 MKAnnotationView 后拖动地图不会移动 MKAnnotationView

PFObject作为MKAnnotation导致NSInternalInconsistencyException