Reputation: 618
At Apple Documentation of setUserTrackingMode:animated:
it is stated that:
Setting the tracking mode to MKUserTrackingModeFollow or MKUserTrackingModeFollowWithHeading causes the map view to center the map on that location and begin tracking the user’s location. If the map is zoomed out, the map view automatically zooms in on the user’s location, effectively changing the current visible region.
My question, is there a way we can retain current zoom level on map, while setting the user tracking mode?
Upvotes: 4
Views: 2853
Reputation: 41
There is a way to do it in a smooth way by getting the location of the default MKUserLocation bubble. Just a note, MKUserLocation.location
will not return smoothed out location as it's updated when location manager updates, but we can get the location of the actual bubble annotation view. We can then use CADisplayLink to update the map every frame:
// in viewDidLoad
displayLink = CADisplayLink(target: self, selector: #selector(displayStep))
displayLink?.add(to: .current, forMode: .default)
@objc
func displayStep(displayLink: CADisplayLink) {
if let annotation = mapView.annotations.filterByType(MKUserLocation.self).first,
let annotationView = mapView.view(for: annotation) {
let smoothedLocation = mapView.convert(annotationView.frame, toRegionFrom: nil).center
//set the camera to the smoothed location
mapView.camera.centerCoordinate = smoothedLocation
}
}
Upvotes: 1
Reputation: 609
As of iOS 13 you can set a minimum map zoom level, which prevents MKUserTrackingModeFollow getting any closer than the specified distance, when it is set:
let minZoom: CLLocationDistance = 10000 // desired visible radius from user in metres
let zoomRange = MKMapView.CameraZoomRange(minCenterCoordinateDistance: minZoom)
mapView.setCameraZoomRange(zoomRange, animated: true)
https://developer.apple.com/documentation/mapkit/mkmapview/camerazoomrange
Upvotes: 2
Reputation: 11
The way i was able to do this was to call a MKCoordinateRegionMakeWithDistance call that uses the users location and center. I used 5000 for my values. This is what my test code looks like. `import UIKit import CoreLocation import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate{
@IBOutlet weak var mapView: MKMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled()){
mapView.showsUserLocation = true
mapView.mapType = MKMapType.satellite
mapView.setUserTrackingMode(MKUserTrackingMode.followWithHeading, animated: true)
//locationManager = CLLocationManager()
//locationManager.delegate = self
//locationManager.desiredAccuracy = kCLLocationAccuracyBest
//locationManager.requestAlwaysAuthorization()
//locationManager.startUpdatingLocation()
}
}
/*func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
let location = locations.last as! CLLocation
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
//let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
let region = MKCoordinateRegionMakeWithDistance(center, 500, 500)
self.mapView.setRegion(region, animated: true)
}*/
@IBAction func centerButton(_ sender: UIButton, forEvent event: UIEvent) {
let location = MKUserLocation()
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegionMakeWithDistance(center, 5000, 5000)
self.mapView.setRegion(region, animated: true)
mapView.setUserTrackingMode(MKUserTrackingMode.followWithHeading, animated: true)
}
} ` dont read any of the commented out locationManager info. The important thing here is to remember that calling setUserTrackingMode does not affect the zoom level but just moves the center to the users location so if you set a zoom level using the region and distance method, and then call setUserTrackingMode it will assume that zoom. This allows me to always zoom out to a reasonable zoom level each time we recenter and follow the users current location.
Upvotes: 1
Reputation: 5128
No. One alternative is you could listen to user location updates yourself (either through Core Location or the MKMapViewDelegate
methods and update the map center, but tracking mode can not guarantee to not change the zoom.
Upvotes: 0