Swift注释没有放置在MapView上,因为viewForAnnotation方法没有被调用。

5

我正在开发一个应用程序,该应用程序会在用户当前位置放置一个标记,并根据用户输入的位置放置其他标记。当前位置的注释已经被正确地放置了,但是当尝试放置用户输入的坐标时,注释没有被放置。

我已经使用map.addAnnotation(annotation)正确地添加了注释,其中注释.coordinate(纽约)为CLLocationCoordinate2D(latitude: 40.713054, longitude: -74.007227999999998)

我发现viewForAnnotation方法没有被调用,我认为这就是注释没有被放置的原因(打印注释不会输出任何结果)。我有一个测试应用程序,可以请求输入坐标并成功放置注释。在测试应用程序中,打印注释会输出一个值。

下面我粘贴了一些我认为与此问题相关的代码。如果需要更多信息,请评论。

import UIKit
import MapKit
import CoreLocation
class MapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {



@IBOutlet weak var map: MKMapView!

override func viewDidLoad() {
    super.viewDidLoad()
    map.delegate = self
}

下面这个函数从另一个类中获取数值并将其转换为CLLocationCoordinate2D类型的坐标。如上所述,annotation.coordinate (对于纽约)返回CLLocationCoordinate2D(latitude: 40.713054, longitude: -74.007227999999998),因此add函数可以成功保存这些坐标。
func add(newLocation location_one:[String:Any]) {
    let momentaryLat = (location_one["latitude"] as! NSString).doubleValue
    let momentaryLong = (location_one["longitude"] as! NSString).doubleValue
    
    let annotation = MKPointAnnotation()
    annotation.title = location_one["title"] as? String
    annotation.coordinate = CLLocationCoordinate2D(latitude: momentaryLat as CLLocationDegrees, longitude: momentaryLong as CLLocationDegrees)
    


    map.addAnnotation(annotation) //not sure if this adds the annotation!

    self.map.centerCoordinate = annotation.coordinate
}

func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

    if (annotation is MKUserLocation) {
        return nil
    }
   
    let identifier = "pinAnnotation"
    var annotationView = map.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
    
    if annotationView == nil {
        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        annotationView?.canShowCallout = true
    
    } else {
        annotationView?.annotation = annotation
    
    }
    map.showAnnotations(map.annotations, animated: true)
    return annotationView
}

"map.addAnnotation(annotation)" 这个在主线程中调用吗? - Lory Huz
add 方法是否被调用了? - Mihai Fratu
@MihaiFratu 我在我的代码中使用了add方法。它在另一个视图控制器中,像这样:map.add(newLocation:location_one)。我的add方法中的annotation.coordinate保存了适当的坐标。我认为问题是我的viewForAnnotation没有被调用。 - Kevin
3个回答

4

首先,

func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?

这是一个代理方法,不用于设置注释,它只是:

  1. 返回与指定注释对象相关联的视图,即显示指定注释或nil的注释视图

  2. 如果您未实现此方法,或者对于用户位置注释以外的注释从实现中返回nil,则地图视图使用标准图钉注释视图。

在此处查看-

https://developer.apple.com/reference/mapkit/mkmapviewdelegate/1452045-mapview

addAnnotation() 方法足以添加默认图钉注释。可能未被调用,因为您可能已经调用了来自后台队列的 func add(newLocation location_one:[String:Any]),该方法在内部调用了 addAnnotatinon() 方法。

如果您正在其他控制器中的某个完成处理程序上调用添加方法,那么您需要明确执行并在主线程上调用添加注释方法。

DispatchQueue.main.async {
    self.map.addAnnotation(annotation) //Yes!! This method adds the annotations
}

为了调试目的,将您的控制器更改为以下内容,即使删除代理,您也能看到注释。
import UIKit
import MapKit

class ViewController:  UIViewController{

@IBOutlet weak var map: MKMapView!

      override func viewDidLoad() {
          super.viewDidLoad()
          let annotation = MKPointAnnotation()
          annotation.title = "Test Location"
          annotation.coordinate = CLLocationCoordinate2D(latitude: 40.71304, longitude: -74.0072)
          self.map.addAnnotation(annotation)
      }
}

请确保-

  1. 从主线程调用addAnnotation方法
  2. 使用viewForAnnotation方法对注释的默认图钉进行自定义。

啊,好的,我明白了,问题在于它没有添加注释,而viewFor与此无关。我对你所说的“主线程”和“后台队列”感到困惑。你能再解释一下吗? - Kevin
我猜为了澄清,我正在从另一个VC传递信息。在mapView VC中,add方法接收来自全局数组的信息,并尝试为每个位置放置注释。是否有一种方法可以将其实现到viewDidLoad中,因为那似乎完美地运行? - Kevin
@Kevin,我在寻找一些更简单的词来帮助你理解后台队列的概念,这个我们之后再讲。现在,你获取的数组是否来自于某个 Web API?而且你不需要特别在 viewDidLoad 中实现,让你之前的代码保持不变,只需将 addAnnotation 替换为 DispatchQueue.main.async { self.map.addAnnotation(annotation) } 即可。 - Saurabh Yadav
不,我没有使用任何Web API(JSON或XML)。我正在使用的数组是由用户从其他视图控制器更新的。用户可以输入地址,我有一个反向地理编码器将地址转换为纬度和经度坐标。 - Kevin
让我们在聊天中继续这个讨论 - Saurabh Yadav
显示剩余4条评论

0

我认为无需使用 viewForAnnotation 函数。只需通过为注释提供坐标并使用 map.addAnnotation(annotation) 函数将其放入地图中即可显示注释。


0
首先,在viewForAnnotation方法中不要调用map.showAnnotations,因为每次MapKit决定绘制注释视图时都会调用该方法--所以如果有多个可用的注释,地图将会令人讨厌地重新定位自己,这可能导致无限循环(对于最后一个我不确定,但我可以想象在某些情况下可能会发生)。您应该仅在用户请求时(例如按钮按下或其他选择)调用map.showAnnotations,以使地图围绕这些注释居中。
不幸的是,您的代码完美地工作了;希望您没有忘记调用add
override func viewDidLoad() {
    super.viewDidLoad()

    let loc = ["latitude": "40.713054", "longitude":"-74.00722", "title": "nyc"]
    add(newLocation: loc)
}

这是结果: {{link1:在此输入图像描述}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接