绘制跟随用户当前位置的MKPolyline [英] Drawing MKPolyline Which Follows User's Current Location

查看:38
本文介绍了绘制跟随用户当前位置的MKPolyline的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

ViewController.swft

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()
        }
    }
}

谢谢!

推荐答案

问题在于,您正在抓取一个位置,将其添加到数组中,然后创建一条从数组中的最后一个位置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. 我建议取消noLocation中的noLocation模式。我的上述模式不需要数组中的该虚拟值。

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

这篇关于绘制跟随用户当前位置的MKPolyline的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆