【问题标题】:Drawing MKPolyline Which Follows User's Current Location绘制跟随用户当前位置的 MKPolyline
【发布时间】:2020-07-24 02:40:29
【问题描述】:

我试图在用户移动时在他们身后绘制一条路径,跟踪他们的路径(就像 Strava 或 FitBit 应用程序在用户开始锻炼时所做的那样)。到目前为止,地图以用户的位置为中心,但不会在用户移动时开始绘制。我曾尝试使用 renderForOverlay 来实现这一点,但在测试时却没有这样做。代码如下:

ViewController.swift

import UIKit
import MapKit
import CoreLocation

class StartWorkoutViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {

    @IBOutlet weak var mapsView: MKMapView!
    @IBOutlet weak var startButton: UIButton!
    
    var locationManager: CLLocationManager!
    var allLocations: [CLLocation] = []
    
    @IBAction func startButton(_ sender: Any) {
        // Start the workout
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Request user's current location
        locationManager = CLLocationManager()
        locationManager?.requestAlwaysAuthorization()
        locationManager?.desiredAccuracy = kCLLocationAccuracyBest
        locationManager?.startUpdatingLocation()
        locationManager?.startUpdatingHeading()
        locationManager?.delegate = self
        
        mapsView?.showsUserLocation = true
        mapsView?.mapType = MKMapType(rawValue: 0)!
        mapsView?.userTrackingMode = .follow
        mapsView?.delegate = self
        
        let noLocation = CLLocationCoordinate2D()
        let viewRegion = MKCoordinateRegion(center: noLocation, latitudinalMeters: 100, longitudinalMeters: 100)
        mapsView?.setRegion(viewRegion, animated: true)
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // Add location to the array and prepare to draw a line between last location and current location
        print("Location Updated")
        allLocations.append(locations[0])
        
        let previousLocation = allLocations[allLocations.count - 1]
        let newLocation = locations[0]
        
        let previousCoordinates = previousLocation.coordinate
        let newCoordinates = newLocation.coordinate
        
        var area = [previousCoordinates, newCoordinates]
        let polyline = MKPolyline(coordinates: &area, count: area.count)
        mapsView.addOverlay(polyline)
    }
    
// DOES NOT WORK
    func mapView(_ mapsView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if overlay is MKPolyline {
            let polylineRenderer = MKPolylineRenderer(overlay: overlay)
            polylineRenderer.strokeColor = UIColor.red
            polylineRenderer.lineWidth = 4
            return polylineRenderer
        } else {
            return MKPolylineRenderer()
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        // If the authorisation for the user's location has changed, ask again
        if status != .authorizedAlways {
            locationManager = CLLocationManager()
            locationManager?.requestAlwaysAuthorization()
        }
    }
}

谢谢!

【问题讨论】:

  • 我看到了一些错误: 1. 在主任务中调用改变 mapsView 的方法 (mapsView.addOverlay(polyline))。 2. 在 didUpdateLocations 中添加折线但从不删除旧折线。 3.return MKPolylineRenderer()没有overlay作为参数,所以Renderer不知道要渲染什么。

标签: ios swift mapkit mkpolyline


【解决方案1】:

问题是您正在抓取一个位置,将其添加到数组中,然后从数组中的最后一个位置allLocations[allLocations.count - 1](现在是当前位置)创建一条折线到当前位置(即对自己)。

因此,在将新位置添加到其中之前,从数组中获取最后一项 previousCoordinate

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let currentLocation = locations.first(where: { $0.horizontalAccuracy >= 0 }) else {
        return
    }

    let previousCoordinate = allLocations.last?.coordinate
    allLocations.append(currentLocation)

    if previousCoordinate == nil { return }

    var area = [previousCoordinate!, currentLocation.coordinate]
    let polyline = MKPolyline(coordinates: &area, count: area.count)
    mapsView.addOverlay(polyline)
}

我还建议,如您在上面看到的,检查位置更新的水平精度,以确保它是非负数。

无论如何,这会产生:


其他一些观察:

  1. 我建议停用 viewDidLoad 中的 noLocation 模式。我上面的模式不需要数组中的虚拟值。

  2. 另一个问题是,在didChangeAuthorization 中,您正在实例化一个新的CLLocationManager,而不是设置它的属性。因此,您将丢失viewDidLoad 中原始CLLocationManager 的配置。无需实例化另一个,但如果您这样做,请记住正确配置它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-04
    • 2018-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多