每次我从当前位置滚动时,MapKit 都会自动缩放回当前位置

Posted

技术标签:

【中文标题】每次我从当前位置滚动时,MapKit 都会自动缩放回当前位置【英文标题】:MapKit auto-zooming back to current location every time I scroll away from current location 【发布时间】:2020-08-26 02:45:04 【问题描述】:

我在 X-code 中构建了一个基本应用程序,它显示用户的位置并自动放大到用户的位置。我希望能够在地图上移动,因为我将在用户位置周围设置重要的注释,但是每次我导航到地图的不同部分时,我都会被拖回放大的位置。有人建议我“处理地图上的平移手势,当地图处于平移状态时不要缩放。您可以使用简单的布尔标志来控制它是否缩放。”请告知关于如何解决这个问题。

import UIKit

导入 MapKit 导入核心位置

类视图控制器:UIViewController、CLLocationManagerDelegate、MKMapViewDelegate

@IBOutlet weak var mapView: MKMapView!
private let locationManager = CLLocationManager()


override func viewDidLoad() 
    super.viewDidLoad()
    
    //delegates
    locationManager.delegate = self
    self.mapView.delegate = self
    
    
    locationManager.requestWhenInUseAuthorization()
    
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = kCLDistanceFilterNone
    
    locationManager.startUpdatingLocation()
    
    self.mapView.showsUserLocation = true



//zoom
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) 
    let region = MKCoordinateRegion(center: mapView.userLocation.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2))
    mapView.setRegion(region, animated: true)

【问题讨论】:

【参考方案1】:

当您设置locationManager.startUpdatingLocation() 时,设备的定位硬件(GPS/无线电接收器等)开始实际尝试确定位置的工作。但是,它会继续这样做,直到你告诉它 locationManager.stopUpdatingLocation() 所以你的应用程序将收到一个持续的位置更新流,这些更新都由你的 mapView 委托函数 mapView didUpdate userLocation 处理,每次调用该方法时,你都在指示mapView 缩放到您用户的位置,因此它正在对抗并覆盖用户尝试同时执行的任何其他操作,例如滚动、缩放等。

位置更新流中的每一个都会有一个位置测量中的不确定性 (.horizontalAccuracy) 数字(+/- 60m 或其他),并且每次连续更新都希望具有比前一次更小的不确定性,但那是'不保证取决于当地的物理环境。

一种常见的方法是,在mapView didUpdate userLocation 中,保留上次更新的副本并将其与每个后续更新进行比较,如果新的比前一个更准确,则保存新的,否则丢弃。计算新旧之间的距离,当该距离小于您之前确定的最小值(kCLLocationAccuracyBest 或 500m、50m、10m 等)然后locationManager.stopUpdatingLocation()

在您决定停止更新位置之前,您应该避免任何类型的自动缩放,因为这种行为会让您的用户感到沮丧。

这是一种典型的方法,但需要根据您的特定用途进行修改:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
    let newLocation = locations.last!
    // We've been passed a cached result so ignore and continue.
    if newLocation.timestamp.timeIntervalSinceNow < -5 
        return
    
    // horizontalAccuracy < 0 indicates invalid result so ignore and continue.
    if newLocation.horizontalAccuracy < 0 
        return
    
    // Calculate the distance between the new and previous locations.
    var distance = CLLocationDistance(Double.greatestFiniteMagnitude)
    if let location = location  // location is my previously stored value.
        distance = newLocation.distance(from: location)
    
    // If newLocation is more accurate than the previous (if previous exists) then use it.
    if location == nil || location!.horizontalAccuracy > newLocation.horizontalAccuracy 
        lastLocationError = nil
        location = newLocation

        // When newLocation's accuracy is better than our desired accuracy then stop.
        if newLocation.horizontalAccuracy <= locationManager.desiredAccuracy 
            stopLocationManager()
        
     else if distance < 5 
        let timeInterval = newLocation.timestamp.timeIntervalSince(location!.timestamp)
        if timeInterval > 10 
            stopLocationManager()
        
    

    print(newLocation)

有时更新根本无法达到满足我们要求的准确性,因此有一个计时器可以在 10 秒后终止位置搜索。

我建议您引入一个执行相同操作的按钮,而不是使用自动缩放到用户的位置。这样用户就可以准确地知道行为发生的时间和原因,如果他们选择缩放到他们的位置,他们就不会同时滚动。

【讨论】:

【参考方案2】:

不确定你是否得到了答案,但这是我处理它的方法。

我只是添加了一个名为 tracking 的 var,它在开始时设置为 true。 我在 viewDidLoad 中调用了 locationManager.stopUpdatingLocation(),然后将跟踪变量设置为 false。

super.viewDidLoad()
checkLocationServices()
    
customers = ReadTextFile()
for customer in customers 
    addCustomPin(customer:customer)

locationManager.stopUpdatingLocation()
tracking = false

在我的 checkLocationServices() 中,它调用 checkLocationAuthorization() 我加了

if tracking 
    locationManager.startUpdatingLocation()

这样,应用第一次调用 checkLocationServices 时,我的跟踪变量为真,因此它会检查位置。

如果我想重新打开设置,我只需要将变量重新设置为 true。

【讨论】:

以上是关于每次我从当前位置滚动时,MapKit 都会自动缩放回当前位置的主要内容,如果未能解决你的问题,请参考以下文章

MapKit 缩放到用户当前位置

转到/缩放到当前位置功能(MapKit)

使用 Alamofire 和 Mapkit Swift 3 请求

Swift Mapkit - 远离用户位置

MapKit iPhone显示器Zoom Controls

Yandex MapKit 3.0。获取屏幕和缩放的中心,在地图上获取位置