如何将MGLAnnotationView设置为popover

时间:2016-12-01 12:05:34

标签: swift annotations mapbox uipopovercontroller

我想要做的是提供一个带有注释作为源视图/锚点的popover

通过使用委托函数 didSelect annotationView ,我应该能够实现这一点,但它似乎根本没有运行。 现在我只是通过 didSelect注释呈现我的popover并将sourceView设置为导航栏,只是为了在某处显示...

供参考: 我已将 Mapbox SDK 实施到项目中。 使用MapKit执行相同的任务没有问题。

有没有人知道我能做些什么来实现这个目标?

下面的代码段:

import UIKit
import Mapbox

class ViewController: UIViewController, MGLMapViewDelegate, UIPopoverPresentationControllerDelegate {

@IBOutlet var theMap: MGLMapView!

override func viewDidLoad() {
    super.viewDidLoad()

    theMap.delegate = self

    let point = MGLPointAnnotation()
    point.coordinate = CLLocationCoordinate2D(latitude: 55.6, longitude: 13.0)
    point.title = "Some place"
    point.subtitle = "Malmö, Sweden"
    theMap.addAnnotation(point)
}

func mapView(_ mapView: MGLMapView, didSelect annotationView: MGLAnnotationView) {
    print("annotation view: ", annotationView)
    // this method doesn't seem to get called at all...
    // but ideally this is the place to present the popover.
}

func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
    print("annotation: ", annotation)
    // present the popover
    presentPopover()
}

func presentPopover(){
    let popover = storyboard?.instantiateViewController(withIdentifier: "MyCalloutVC") as! MyCallout

    popover.modalPresentationStyle = UIModalPresentationStyle.popover
    popover.popoverPresentationController?.backgroundColor = UIColor.white
    popover.popoverPresentationController?.delegate = self

    // I would like to set the source anchor to the selected annotation view.
    popover.popoverPresentationController?.sourceView = UINavigationBar() // set to nav bar for now...
    popover.popoverPresentationController?.permittedArrowDirections = .any
    // popover size set in MyCallout 
    self.present(popover, animated: true)
    }
}

1 个答案:

答案 0 :(得分:0)

由于没有可以选择的注释视图,因此不会调用该函数。 这意味着您只需添加点注释而不是注释视图。因此,您必须这样做: 当您添加注释时,func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {}被调用,您可以在其中定义注释视图并返回它。然后将调用所选择的功能。看一下示例代码:https://www.mapbox.com/ios-sdk/examples/annotation-views/

import Mapbox

// Example view controller
class ViewController: UIViewController, MGLMapViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let mapView = MGLMapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.styleURL = MGLStyle.darkStyleURL(withVersion: 9)
        mapView.tintColor = .lightGray
        mapView.centerCoordinate = CLLocationCoordinate2D(latitude: 0, longitude: 66)
        mapView.zoomLevel = 2
        mapView.delegate = self
        view.addSubview(mapView)

        // Specify coordinates for our annotations.
        let coordinates = [
            CLLocationCoordinate2D(latitude: 0, longitude: 33),
            CLLocationCoordinate2D(latitude: 0, longitude: 66),
            CLLocationCoordinate2D(latitude: 0, longitude: 99),
        ]

        // Fill an array with point annotations and add it to the map.
        var pointAnnotations = [MGLPointAnnotation]()
        for coordinate in coordinates {
            let point = MGLPointAnnotation()
            point.coordinate = coordinate
            point.title = "\(coordinate.latitude), \(coordinate.longitude)"
            pointAnnotations.append(point)
        }

        mapView.addAnnotations(pointAnnotations)
    }

    // MARK: - MGLMapViewDelegate methods

    // This delegate method is where you tell the map to load a view for a specific annotation. To load a static MGLAnnotationImage, you would use `-mapView:imageForAnnotation:`.
    func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
        // This example is only concerned with point annotations.
        guard annotation is MGLPointAnnotation else {
            return nil
        }

        // Use the point annotation’s longitude value (as a string) as the reuse identifier for its view.
        let reuseIdentifier = "\(annotation.coordinate.longitude)"

        // For better performance, always try to reuse existing annotations.
        var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)

        // If there’s no reusable annotation view available, initialize a new one.
        if annotationView == nil {
            annotationView = CustomAnnotationView(reuseIdentifier: reuseIdentifier)
            annotationView!.frame = CGRect(x: 0, y: 0, width: 40, height: 40)

            // Set the annotation view’s background color to a value determined by its longitude.
            let hue = CGFloat(annotation.coordinate.longitude) / 100
            annotationView!.backgroundColor = UIColor(hue: hue, saturation: 0.5, brightness: 1, alpha: 1)
        }

        return annotationView
    }

    func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
        return true
    }
}

//
// MGLAnnotationView subclass
class CustomAnnotationView: MGLAnnotationView {
    override func layoutSubviews() {
        super.layoutSubviews()

        // Force the annotation view to maintain a constant size when the map is tilted.
        scalesWithViewingDistance = false

        // Use CALayer’s corner radius to turn this view into a circle.
        layer.cornerRadius = frame.width / 2
        layer.borderWidth = 2
        layer.borderColor = UIColor.white.cgColor
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Animate the border width in/out, creating an iris effect.
        let animation = CABasicAnimation(keyPath: "borderWidth")
        animation.duration = 0.1
        layer.borderWidth = selected ? frame.width / 4 : 2
        layer.add(animation, forKey: "borderWidth")
    }
}