Mapkit - Swift4 - How to disable Auto zooming - ios

Apologies for the absurdely junior question but for some reason I can't grasp how to stop this from happening.
When I run the app, and I pinch to zoom into the map (or out, or navigate away from my position) the app will always pull me back to a set height and to my location. I'd like to not have this happen and just have the experience of zooming to whatever level and moving around without being interrupted.
Any ideas?
Here's the code snip from my VC:
let regionRadius: CLLocationDistance = 2000
func centerMapOnLocation(location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, regionRadius, regionRadius)
mapView.setRegion(coordinateRegion, animated: true)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let center = location.coordinate
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let region = MKCoordinateRegion(center: center, span: span)
mapView.setRegion(region, animated: true)
mapView.showsUserLocation = true
}
Thanks for any help

Location Manager delegate methods can be called very frequently and at any time. So you need to stop updating locations.
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation()
manager.delegate = nil
let location = locations[0]
...
}

Related

Prevent zooming/heading update stop in iOS MKMapView

In iOS I have an MKMapView and CLLocationManager to update the heading and location. No matter what I do, I can't get the map view to stop zooming in tightly on the user's location. I have annotations on the map that I want visible at all times, and I want the heading to update as the user spins the device. This is working using mapView.setRegion, but after a bit, the map locks at the north and no longer rotates. Below is the CLLocationManager code I'm using:
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
if data != nil{
setRegion(locationManager?.location?.coordinate.latitude)!, longitude: (locationManager?.location?.coordinate.longitude)!), data: data!)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if !regionSet && data != nil{
setRegion(location: CLLocationCoordinate2D(latitude: (locationManager?.location?.coordinate.latitude)!, longitude: (locationManager?.location?.coordinate.longitude)!), data: data!)
regionSet = true
}
}
setRegion calculates the extents of the map to zoom on and sets the setRegion function appropriately.
Below is setRegion. I calculate the zoomWindowDegrees variable when I load in the annotations by finding the maximum lat/long for the annotations and the use that in the function.
private func setRegion(location:CLLocationCoordinate2D, towers:[Tower]){
let center = location
let coordinateSpan = MKCoordinateSpan(latitudeDelta: zoomWindowDegrees, longitudeDelta: zoomWindowDegrees)
let region = MKCoordinateRegion(center: center, span: coordinateSpan)
mapView.setRegion(region, animated: false)
}

mapView.setRegion in Swift 4

I am having problems with my code in Swift 4, Xcode 9. Can someone help me?
When I run this program it gives me an error.
It says mapView.setRegion(region, animated: true) is not working and giving my an error and when I comment that out, it works with my current location but just not zoomed in closely.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
if !isInitialized {
isInitialized = true
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapView.setRegion(region, animated: true)
self.mapView.showsUserLocation = true
}
}
I'll bet you just forgot to link up your mapView with the storyboard. Make sure it's connected properly as an #IBOutlet and try again.

Retain map zoom level while there is a change in location

I am using a MKMapView application. but when zoom into the map to the current user location, the map zooms well. But when there is a change in current location, the map automatically zooms out to the original position where it all started. How can I retain the same level of zoom even when the location changes. Thank you.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let latestlocation:CLLocation = locations[locations.count-1]
let a = latestlocation.coordinate.latitude
let b = latestlocation.coordinate.longitude
let center = CLLocationCoordinate2D(latitude: a, longitude: b)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpanMake(0.05, 0.05))
self.mapView.setRegion(region, animated: false)
mapView.setUserTrackingMode(.follow, animated: true)
self.mapView.showsUserLocation = true
}

MapKit View not zooming in to users location

In my application I have a MKMapKit view and when my application starts, if the user allows location services, I want the Map to zoom into the user's location. The code I wrote is:
override func viewDidLoad() {
super.viewDidLoad()
mapKitView.delegate = self
mapKitView.showsUserLocation = true
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
if (CLLocationManager.locationServicesEnabled()) {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
}
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
}
DispatchQueue.main.async {
self.locationManager.startUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
let noLocation = CLLocationCoordinate2D()
let viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 200, 200)
mapKitView.setRegion(viewRegion, animated: false)
}
In my app, it shows the users location, but does not animate and zoom in.
Use the user's location to calculate the view region and change the animated parameter to true:
if let location = mapKitView.userLocation.location {
let viewRegion = MKCoordinateRegionMakeWithDistance(location, 200, 200)
mapKitView.setRegion(viewRegion, animated: true)
}
In Swift 3.0, try my code in your didUpdateLocation method.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
//get location cordinate
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
print(locValue)
//set updating location stop
locationManager.stopUpdatingLocation()
let location = locations.last! as CLLocation//create object of CLLocation
//get location cordinate
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
//set map zooming using region
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
}
I hope it's work #Rahul Bir
In Swift 3.0 you should use this code if you want to zoom map Kit on the starting view of the map view.
var zoomIn = false
var zoomAnnotation:MKAnnotation
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if let annotation = zoomAnnotation where zoomIn == true {
let region = MKCoordinateRegion(center: zoomAnnotation.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.075, longitudeDelta: 0.075))
mapView.setRegion(region, animated: true)
zoomIn = false
}
}

Show Current Location and Update Location in MKMapView in Swift

I am learning how to use the new Swift language (only Swift, no Objective-C). To do it, I want to do a simple view with a map (MKMapView). I want to find and update the location of the user (like in the Apple Map app).
I tried this, but nothing happened:
import MapKit
import CoreLocation
class MapView : UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled())
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
}
}
Could you please help me?
You have to override CLLocationManager.didUpdateLocations (part of CLLocationManagerDelegate) to get notified when the location manager retrieves the current location:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last{
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.map.setRegion(region, animated: true)
}
}
NOTE: If your target is iOS 8 or above, you must include the NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in your Info.plist to get the location services to work.
100% working, easy steps and tested
Import libraries:
import MapKit
import CoreLocation
set delegates:
CLLocationManagerDelegate,MKMapViewDelegate
Take variable:
let locationManager = CLLocationManager()
write this code on viewDidLoad():
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
if let coor = mapView.userLocation.location?.coordinate{
mapView.setCenter(coor, animated: true)
}
Write delegate method for location:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
mapView.mapType = MKMapType.standard
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: locValue, span: span)
mapView.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = locValue
annotation.title = "Javed Multani"
annotation.subtitle = "current location"
mapView.addAnnotation(annotation)
//centerMap(locValue)
}
Do not forgot to set permission in info.plist
<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
It's look like:
For swift 3 and XCode 8 I find this answer:
First, you need set privacy into info.plist. Insert string NSLocationWhenInUseUsageDescription with your description why you want get user location. For example, set string "For map in application".
Second, use this code example
#IBOutlet weak var mapView: MKMapView!
private var locationManager: CLLocationManager!
private var currentLocation: CLLocation?
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
// Check for Location Services
if CLLocationManager.locationServicesEnabled() {
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
}
// MARK - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
defer { currentLocation = locations.last }
if currentLocation == nil {
// Zoom to user location
if let userLocation = locations.last {
let viewRegion = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 2000, 2000)
mapView.setRegion(viewRegion, animated: false)
}
}
}
Third, set User Location flag in storyboard for mapView.
MyLocation
is a Swift iOS Demo.
You can use this demo for the following:
Show the current location.
Choose other location: in this case stop tracking the location.
Add a push pin to a MKMapView(iOS) when touching.
Hi Sometimes setting the showsUserLocation in code doesn't work for some weird reason.
So try a combination of the following.
In viewDidLoad()
self.mapView.showsUserLocation = true
Go to your storyboard in Xcode, on the right panel's attribute inspector tick the User location check box, like in the attached image. run your app and you should be able to see the User location
Swift 5.1
Get Current Location and Set on MKMapView
Import libraries:
import MapKit
import CoreLocation
set delegates:
CLLocationManagerDelegate , MKMapViewDelegate
Declare variable:
let locationManager = CLLocationManager()
Write this code on viewDidLoad():
self.locationManager.requestAlwaysAuthorization()
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
if let coor = mapView.userLocation.location?.coordinate{
mapView.setCenter(coor, animated: true)
}
Write delegate method for location:
func locationManager(_ manager: CLLocationManager, didUpdateLocations
locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
mapView.mapType = MKMapType.standard
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let region = MKCoordinateRegion(center: locValue, span: span)
mapView.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = locValue
annotation.title = "You are Here"
mapView.addAnnotation(annotation)
}
Set permission in info.plist *
<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
For Swift 2, you should change it to the following:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.map.setRegion(region, animated: true)
}
You just need to set the userTrackingMode of the MKMapView. If you only want to display and track the user location and implement the same behaviour as the Apple Maps app uses, there is no reason for writing additional code.
mapView.userTrackingMode = .follow
See more at https://developer.apple.com/documentation/mapkit/mkmapview/1616208-usertrackingmode .
you have to override CLLocationManager.didUpdateLocations
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
locationManager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.5, 0.5)
let region = MKCoordinateRegion (center: location,span: span)
mapView.setRegion(region, animated: true)
}
you also have to add NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription to your plist setting Result as value
In Swift 4, I had used the locationManager delegate function as defined above ..
func locationManager(manager: CLLocationManager!,
didUpdateLocations locations: [AnyObject]!) {
.. but this needed to be changed to ..
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
This came from .. https://github.com/lotfyahmed/MyLocation/blob/master/MyLocation/ViewController.swift - thanks!
mapView.showsUserLocation = true
Create UIButton and add this action
#IBAction func showCurrentLocation(_ sender: Any) {
let coordinate = mapView.userLocation.coordinate
let center = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
}

Resources