簡體   English   中英

通過 iOS 上的 Mapbox 中的按鈕在當前位置添加 Maker

[英]Add Maker at current location via Button in Mapbox on iOS

我正在嘗試構建一個應用程序,我可以通過按下按鈕向 map 添加標記。 我已經可以通過按下按鈕來實現這一點,當前位置和默認標題以MGLPointAnnotation類型寫入數組。 但我對新注釋的可視化感到困惑。 我總是得到錯誤

Type of expression is ambiguous without more context

到目前為止,這是我的代碼:

func makeEntry(){
        guard let locValue: CLLocationCoordinate2D = locationManager.location?.coordinate else { return }

        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()

        let point = Annotation()
        point.coordinate = CLLocationCoordinate2D(latitude: (locValue.latitude), longitude: (locValue.longitude))
        point.title = "Entry"
        pointAnnotations.append(point)
        mapView.addAnnotations(pointAnnotations) <-- triggers the error waring
        }

我是 Swift 的新手,希望你能幫助我。

編輯:

這是應用程序核心功能的rest:

func addButton(){
        entryButton = UIButton(frame: CGRect(x: (view.frame.width/2)-100 , y: (view.frame.height)-75, width: 200, height: 50))
        entryButton.setTitle("Neuer Eintrag", for: .normal)
        entryButton.setTitleColor(UIColor(red: 100/255, green: 180/255, blue: 40/255, alpha: 1), for: .normal)
        entryButton.backgroundColor=(UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1))
        entryButton.layer.cornerRadius = 20
        entryButton.addTarget(self, action: #selector(entryButtonWasPressed(_sender:)), for: .touchUpInside)
        view.addSubview(entryButton)
    }
    @objc func entryButtonWasPressed(_sender: UIButton){
        makeEntry()
        print(pointAnnotations)   
    }

編輯編輯:這是完整的代碼:

import UIKit
import Mapbox

class ViewController: UIViewController, MGLMapViewDelegate {
    let point = MGLPointAnnotation()
    var entryButton: UIButton!
    let locationManager = CLLocationManager()
    var annotation = MGLPointAnnotation()
    var pointAnnotations = [MGLPointAnnotation]()

    override func viewDidLoad() {
        super.viewDidLoad()
        let mapView = MGLMapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.delegate = self

        // Enable heading tracking mode so that the arrow will appear.
        mapView.userTrackingMode = .followWithHeading

        // Enable the permanent heading indicator, which will appear when the tracking mode is not `.followWithHeading`.
        mapView.showsUserHeadingIndicator = true
        view.addSubview(mapView)

        // Set the map view's delegate
        mapView.delegate = self

        // Allow the map view to display the user's location
        mapView.showsUserLocation = true

        addButton()
        }

    func addButton(){
        entryButton = UIButton(frame: CGRect(x: (view.frame.width/2)-100 , y: (view.frame.height)-75, width: 200, height: 50))
        entryButton.setTitle("New Entry", for: .normal)
        entryButton.setTitleColor(UIColor(red: 100/255, green: 180/255, blue: 40/255, alpha: 1), for: .normal)
        entryButton.backgroundColor=(UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1))
        entryButton.layer.cornerRadius = 20
        entryButton.addTarget(self, action: #selector(entryButtonWasPressed(_sender:)), for: .touchUpInside)
        view.addSubview(entryButton)
    }


    @objc func entryButtonWasPressed(_sender: UIButton){
        makeEntry()
        print(pointAnnotations)
    }


    func makeEntry(){
        guard let locValue: CLLocationCoordinate2D = locationManager.location?.coordinate else { return }

        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()

        let point = MGLPointAnnotation()
        point.coordinate = CLLocationCoordinate2D(latitude: (locValue.latitude), longitude: (locValue.longitude))
        point.title = "Entry"
        pointAnnotations.append(point)
//        mapView.addAnnotations(pointAnnotations)
    }

        func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
        // Always allow callouts to popup when annotations are tapped.
        return true
        }

        func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
        let camera = MGLMapCamera(lookingAtCenter: annotation.coordinate, fromDistance: 4500, pitch: 15, heading: 0)
        mapView.fly(to: camera, withDuration: 2,
        peakAltitude: 3000, completionHandler: nil)
        }
    }

    func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
        // Substitute our custom view for the user location annotation. This custom view is defined below.
        if annotation is MGLUserLocation && mapView.userLocation != nil {
            return CustomUserLocationAnnotationView()
        }
        return nil
    }

    // Optional: tap the user location annotation to toggle heading tracking mode.
    func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
        if mapView.userTrackingMode != .followWithHeading {
            mapView.userTrackingMode = .followWithHeading
        } else {
            mapView.resetNorth()
        }

        // We're borrowing this method as a gesture recognizer, so reset selection state.
        mapView.deselectAnnotation(annotation, animated: false)
    }


// Create a subclass of MGLUserLocationAnnotationView.
class CustomUserLocationAnnotationView: MGLUserLocationAnnotationView {
    let size: CGFloat = 48
    var dot: CALayer!
    var arrow: CAShapeLayer!

    // -update is a method inherited from MGLUserLocationAnnotationView. It updates the appearance of the user location annotation when needed. This can be called many times a second, so be careful to keep it lightweight.
    override func update() {
        if frame.isNull {
            frame = CGRect(x: 0, y: 0, width: size, height: size)
            return setNeedsLayout()
        }

        // Check whether we have the user’s location yet.
        if CLLocationCoordinate2DIsValid(userLocation!.coordinate) {
            setupLayers()
            updateHeading()
        }
    }

    private func updateHeading() {
        // Show the heading arrow, if the heading of the user is available.
        if let heading = userLocation!.heading?.trueHeading {
            arrow.isHidden = false

            // Get the difference between the map’s current direction and the user’s heading, then convert it from degrees to radians.
            let rotation: CGFloat = -MGLRadiansFromDegrees(mapView!.direction - heading)

            // If the difference would be perceptible, rotate the arrow.
            if abs(rotation) > 0.01 {
                // Disable implicit animations of this rotation, which reduces lag between changes.
                CATransaction.begin()
                CATransaction.setDisableActions(true)
                arrow.setAffineTransform(CGAffineTransform.identity.rotated(by: rotation))
                CATransaction.commit()
            }
        } else {
            arrow.isHidden = true
        }
    }

    private func setupLayers() {
        // This dot forms the base of the annotation.
        if dot == nil {
            dot = CALayer()
            dot.bounds = CGRect(x: 0, y: 0, width: size, height: size)

            // Use CALayer’s corner radius to turn this layer into a circle.
            dot.cornerRadius = size / 2
            dot.backgroundColor = super.tintColor.cgColor
            dot.borderWidth = 4
            dot.borderColor = UIColor.white.cgColor
            layer.addSublayer(dot)
        }

        // This arrow overlays the dot and is rotated with the user’s heading.
        if arrow == nil {
            arrow = CAShapeLayer()
            arrow.path = arrowPath()
            arrow.frame = CGRect(x: 0, y: 0, width: size / 2, height: size / 2)
            arrow.position = CGPoint(x: dot.frame.midX, y: dot.frame.midY)
            arrow.fillColor = dot.borderColor
            layer.addSublayer(arrow)
        }
    }

    // Calculate the vector path for an arrow, for use in a shape layer.
    private func arrowPath() -> CGPath {
        let max: CGFloat = size / 2
        let pad: CGFloat = 3

        let top =    CGPoint(x: max * 0.5, y: 0)
        let left =   CGPoint(x: 0 + pad,   y: max - pad)
        let right =  CGPoint(x: max - pad, y: max - pad)
        let center = CGPoint(x: max * 0.5, y: max * 0.6)

        let bezierPath = UIBezierPath()
        bezierPath.move(to: top)
        bezierPath.addLine(to: left)
        bezierPath.addLine(to: center)
        bezierPath.addLine(to: right)
        bezierPath.addLine(to: top)
        bezierPath.close()

        return bezierPath.cgPath
    }
}

編輯******************************************編輯

我將您的整個代碼復制/粘貼到一個新的 Mapbox 項目中並在模擬器上運行它。 它在我的模擬位置編譯並顯示了通常的(小)藍點。 按下按鈕什么也沒做 - 沒有新的注釋,也沒有錯誤消息。

查看您的代碼,您可以看到在ViewController class 之外有兩個方法。 他們只是漂浮在無人區。 其中之一是委托方法:

func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView?

如果將此方法移回ViewController class 內部,它將在需要時調用,並為您想要的用戶位置提供自定義外觀,即。 大藍點。

class 之外的另一種方法是:

func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation)

但是,您已經在 class 中擁有此方法的另一個版本,因此您可能希望將兩者的功能組合到 class內部的一個中,然后擺脫外部的。

您遇到“模糊”錯誤消息的原因是您在 ViewDidLoad 中聲明mapView ,因此它在ViewDidLoad中的任何其他方法中都不可用。 相反,在方法外部聲明mapView以及其他 class 屬性,然后在ViewDidLoad中正常使用它,如下所示:

var annotation = MGLPointAnnotation()
var pointAnnotations = [MGLPointAnnotation]()

var mapView: MGLMapView! // Declared here

override func viewDidLoad() {
    super.viewDidLoad()

    mapView = MGLMapView(frame: view.bounds) // Instantiated here. (No `let`)
    mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    mapView.delegate = self

現在,您的按鈕將在用戶位置放置一個標准注釋。 你可以在你的大藍點后面看到它。 如果其中任何一個不清楚,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM