每次我从当前位置滚动时,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 都会自动缩放回当前位置的主要内容,如果未能解决你的问题,请参考以下文章