NSLocation doesn't wait for me to click allow - ios

When I run the code, the window pops asking for permission to use location but disappears almost immediately, not giving the user a chance to click "Allow". Is there a way to force this action before proceeding?
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
var map:MKMapView?
var manager:CLLocationManager!
convenience init(frame:CGRect){
self.init(nibName: nil, bundle: nil)
self.view.frame = frame
self.map = MKMapView(frame: frame)
self.map!.delegate = self
self.view.addSubview(self.map!)
}
override func viewDidLoad() {
super.viewDidLoad()
// Core Location
manager = CLLocationManager()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
}
func locationManager(manager: CLLocationManager!,
didChangeAuthorizationStatus status: CLAuthorizationStatus){
print("The authorization status of location services is changed to: ")
switch CLLocationManager.authorizationStatus(){
case .Denied:
println("Denied")
case .NotDetermined:
println("Not determined")
case .Restricted:
println("Restricted")
default:
println("Authorized")
}
}
func displayAlertWithTitle(title: String, message: String){
let controller = UIAlertController(title: title,
message: message,
preferredStyle: .Alert)
controller.addAction(UIAlertAction(title: "OK",
style: .Default,
handler: nil))
presentViewController(controller, animated: true, completion: nil)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if CLLocationManager.locationServicesEnabled(){
switch CLLocationManager.authorizationStatus(){
case .Denied:
displayAlertWithTitle("Not Determined",
message: "Location services are not allowed for this app")
case .NotDetermined:
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
case .Restricted:
displayAlertWithTitle("Restricted",
message: "Location services are not allowed for this app")
default:
println("Default")
}
} else {
println("Location services are not enabled")
}
}
func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject]) {
var userLocation:CLLocation = locations[0] as! CLLocation
var latitude:CLLocationDegrees = userLocation.coordinate.latitude
var longitude:CLLocationDegrees = userLocation.coordinate.longitude
var latDelta:CLLocationDegrees = 1.0
var lonDelta:CLLocationDegrees = 1.0
var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
var location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
var region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
map!.setRegion(region, animated: true)
manager.stopUpdatingLocation()
}

Please try this:
import UIKit
import GoogleMaps
import CoreLocation
class StartViewController: UIViewController,CLLocationManagerDelegate,GMSMapViewDelegate {
var locationManager: CLLocationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
setupLocationManager()
}
func setupLocationManager() {
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
locationHandler()
}
func locationHandler() {
if CLLocationManager.locationServicesEnabled() == true {
if (CLLocationManager.authorizationStatus() == .denied) {
// The user denied authorization
} else if (CLLocationManager.authorizationStatus() == .authorizedAlways) {
// The user accepted authorization
} else if (CLLocationManager.authorizationStatus() == .notDetermined){
// The user not determiend authorization
}else if (CLLocationManager.authorizationStatus() == .authorizedWhenInUse){
// In use
}else{ }
}else{
//Access to user location permission denied!
}
}
}//class
Be successful.

It's because you're calling manager.startUpdatingLocation() before you get the result from the manager.requestWhenInUseAuthorization(). Even though you call requestWhenInUseAuthorization, you're updating the user's location before you ever get the result of that method (I had the exact same question as you, actually!)
The answer to that question explains the solution well. Basically, you'll need to implement the locationManager:didChangeAuthorizationStatus delegate method, which is called any time the authorization status changes based on user input. If the user did authorize tracking, then you can call manager.startUpdatingLocation().
Also, for a Swift example of how to implement these methods, take look at this guide.

Related

Cannot assign locationManager() function to DispatchQueue.main.async { * }

I am getting an error while trying to assign function locationManager() in the DispatchQueue.main.async {}, ill provide whole code and specific pic of error for more clarity --> Here
I got most of the code from SeanAllen on yt since I am new to swift and learning everyday so this code isn't my logic, and the function fetchAndReloadData() is my functionalists I created to get the lat and long from the API assigning to the correct car id since it will track Vehicles on map (car tracking app)
class MapViewController: UIViewController, MKMapViewDelegate {
var globalVechicle = [Vehicles]()
var id = "6438367CC43848B497FE4604AF465D6A"
let locationManager = CLLocationManager()
let regionInMeters: Double = 10000
#IBOutlet weak var mapView: MKMapView!
#IBAction func changeMapType(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
mapView.mapType = .standard
}else {
mapView.mapType = .satellite
}
}
#IBAction func closeButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
checkLocationServices()
}
func setupLocationManager() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
func centerViewOnUserLocation() {
if let location = locationManager.location?.coordinate {
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
mapView.setRegion(region, animated: true)
}
}
func checkLocationServices() {
if CLLocationManager.locationServicesEnabled() {
setupLocationManager()
checkLocationAuthorization()
} else {
// show alert they have to turn it on
}
}
func checkLocationAuthorization() {
switch CLLocationManager.authorizationStatus() {
case .authorizedWhenInUse:
mapView.showsUserLocation = true
centerViewOnUserLocation()
fetchAndReloadData()
locationManager.startUpdatingLocation()
break
case .denied:
// show alert instructing them how to turn on the permissions
break
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .restricted:
// Show an alert letting them know what's up
break
case .authorizedAlways:
break
#unknown default:
print("Error")
}
}
}
extension MapViewController: CLLocationManagerDelegate {
func fetchAndReloadData(){
APICaller.shared.getVehicles(for: id) {[weak self] (result) in
guard let self = self else { return }
switch result {
case .success(let vehicle):
self.globalVechicle = vehicle
DispatchQueue.main.async {
self.locationManager()
}
case .failure(let error):
print(error)
}
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let lattitude = globalVechicle[0].Latitude ,let longitude = globalVechicle[0].Longitude else { return }
let carLocation = CLLocationCoordinate2D(latitude: lattitude , longitude: longitude)
let region = MKCoordinateRegion.init(center: carLocation, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
mapView.setRegion(region, animated: true)
mapView.delegate = self
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
checkLocationAuthorization()
}
}

How to prevent iOS app from being suspended

I have an iOS app that needs to track user's geolocation for a research project. However, the app gets automatically suspended by the iOS after a few hours and the geolocation tracking stops working.
Geofencing is not sufficient for my case as it's not accurate enough.
Is there any way to can prevent the app from getting suspended (unless user manually terminate it)?
One way I thought of is to play a silent music indefinitely, and display the music controls on lockscreen through MPRemoteCommandCenter, like how Spotify works.
Would that keep the app alive? (as I believe Spotify never gets killed unless user manually terminate it?)
I have similar app which uses user location for tracking. Check if you have all these permissions in info.plist. And specifically tell users why you are using location permissions
<key>NSLocationAlwaysUsageDescription</key>
<string>Application needs permission to access your current location.
</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Application needs permission to access your current location.
</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
Here is a part of my code. I have removed the unwanted part so you might have to edit while using it.
import GooglePlaces
import GoogleMaps
class StartRideViewController: UIViewController, CLLocationManagerDelegate, GMSMapViewDelegate{
var mapView: GMSMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: Notification.Name.UIApplicationWillResignActive, object: nil)
notificationCenter.addObserver(self, selector: #selector(appMovedToForeGround), name: Notification.Name.UIApplicationDidBecomeActive, object: nil)
}
#objc func appMovedToBackground() {
print("App moved to background!")
print(isStartRide)
if isStartRide == false{
btn_Share.isHidden = true
locationManager.allowsBackgroundLocationUpdates = false
locationManager.stopUpdatingLocation()
}
}
#objc func appMovedToForeGround() {
//getMeRidersData()
}
func initiateLocation(){
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.distanceFilter = 1
locationManager.startUpdatingLocation()
//locationManager.startUpdatingHeading()
locationManager.allowsBackgroundLocationUpdates = true
//checkForLocationServices()
checkLocationAuthorizationStatus()
guard let myLatitude = locationManager.location?.coordinate.latitude else{
return
}
guard let myLongitude = locationManager.location?.coordinate.longitude
else{
return
}
showMap(myLatitude:myLatitude, myLongitude:myLongitude)
}
func showMap(myLatitude:Double, myLongitude:Double){
let camera = GMSCameraPosition.camera(withLatitude: myLatitude,
longitude: myLongitude, zoom: 17)
mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
//mapView = GMSMapView.map(withFrame: CGRect(x: 0, y: 0, width:
self.view.frame.width, height: self.view.frame.height - 250), camera: camera)
mapView?.center = self.view.center
self.view.addSubview(mapView!)
mapView.padding = UIEdgeInsetsMake(150, 0, 80, 0)
mapView.settings.myLocationButton = true
mapView.delegate = self
//mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.isMyLocationEnabled = true
frameForMapView.addSubview(mapView)
}
func checkLocationAuthorizationStatus() {
let status = CLLocationManager.authorizationStatus()
if status == CLAuthorizationStatus.notDetermined{
print("NotDetermined")
locationManager.requestWhenInUseAuthorization()
CLLocationManager.locationServicesEnabled()
locationManager.requestLocation()
}else {
print("Problem with authorization")
}
}
// Handle incoming location events.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
moveMyImageOnMap()
print(isStartRide, gotCounterFromLastRide , counter)
if isStartRide && gotCounterFromLastRide{
updateMyLocationToDataBase()
}
}
// func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
// print(newHeading)
// }
// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
print("Location access was restricted.")
case .denied:
print("User denied access to location.")
// Display the map using the default location.
case .notDetermined:
print("Location status not determined.")
case .authorizedAlways: fallthrough
case .authorizedWhenInUse:
print("Location status is OK.")
if mapView != nil {
mapView.isMyLocationEnabled = true
}
}
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as! String
let msg :String = "You have denied the app to access your location. Please enable the location services in your settings for the app to get the location";
let alertController = UIAlertController(title: "Allow \(appName) to access your location while you are using the app?", message: msg, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "CANCEL", style: UIAlertActionStyle.default, handler: nil)
let settingsAction = UIAlertAction(title: "SETTINGS", style: .default) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
print("Settings opened: \(success)") // Prints true
})
}
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.present(alertController, animated: true, completion: nil)
}
}

Can't get coordinates from CLLocationManager in separate variable/constant

I'm trying to set a variable/constant in Swift using a value from a function which finds the user's current location whilst the app is open. When I uncomment the print function it successfully prints the coordinates but I can't access the value outside of the function.
I currently have this as a part of my code which is in the MainVC.swift file as part of the MainVC class:
import UIKit
import MapKit
import CoreLocation
class MainVC: UIViewController, CLLocationManagerDelegate {
//Map
#IBOutlet weak var map: MKMapView!
let manager = CLLocationManager()
let coordinates = locationManager()
//I've also tried using let coordinates = currentCoords
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) -> String {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
map.setRegion(region, animated: true)
lat = String(myLocation.latitude)
long = String(myLocation.longitude)
let currentCoords:String = "\(lat);\(long)"
//print(currentCoords)
self.map.showsUserLocation = true
return currentCoords
}
}
However I'm faced with this error:
"Cannot use instance member 'locationManager' within property initializer; property initializers run before 'self' is available".
When I change the code and use
let coordinates = currentCoords
I get another error showing:
"Use of unresolved identifier 'currentCoords'"
I have also tried using a lazy var and lazy let.
You should just be able to access locationManager.location?.coordinate as in my buttonClick method :
import UIKit
import MapKit
class ViewController: UIViewController,CLLocationManagerDelegate,MKMapViewDelegate {
let locationManager = CLLocationManager()
#IBAction func buttonClick(_ sender: Any) {
let location = locationManager.location?.coordinate
let lat:Double = (location?.latitude)!
let lon:Double = (location?.longitude)!
print(lat,lon)
}
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
locationManager.delegate = self
locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("viewDidAppear")
// status is not determined
if CLLocationManager.authorizationStatus() == .notDetermined {
locationManager.requestAlwaysAuthorization()
}
// authorization were denied
else if CLLocationManager.authorizationStatus() == .denied {
showAlert("Location services were previously denied. Please enable location services for this app in Settings.")
}
// we do have authorization
else if CLLocationManager.authorizationStatus() == .authorizedAlways {
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("didUpdateLocations")
print(locations.last?.coordinate)
}
func showAlert(_ title: String) {
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
}
This is how you define your public variable
let coordinates:CLLocation = nil
Then in your didUpdateLocations assign the coordinates variable with last element of locations array. Then you'll have access to it everywhere.
Keep in mind didUpdateLocations may be called even up to a few seconds later so your public variable coordinates will be populated after may be up to a few seconds or so.
func coordinatesBecomeAvailable() {
// Here you can print your coordinates or start using them for the first time
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let firstTime:Bool = (coordinates == nil)
coordinates = locations[0]
if (firstTime) // This is first time this function is called
coordinatesBecomeAvailable()
......
< Rest of your code here >
......
< This function does have any return value! no String nothing >
}
You just need to check whether the value of coordinates is nil or not.
Or you can check inside the didUpdateLocations whether this is the first time this delegate method is called.
This is not the most efficient and completed way of initializing and using location manager and I assume you just posted the code related to your problem.

Repeating location data with CLLocation

This is a really basic outlay of what I am using...
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
// Call the locationManager class
let LocationManager = CLLocationManager()
// CoreData Delegate
let appDelegate = UIApplication.shared.delegate as! AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
// Conform to Delegate Method
self.LocationManager.delegate = self
// Set required accuracy
self.LocationManager.desiredAccuracy = kCLLocationAccuracyBest
// Blue dot
self.mapView.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// check location services active
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// check location services
switch CLLocationManager.authorizationStatus() {
case .authorizedAlways:
self.LocationManager.startUpdatingLocation()
case .notDetermined:
self.LocationManager.requestAlwaysAuthorization()
case .authorizedWhenInUse, .restricted, .denied:
let alertController = UIAlertController(
title: "Background Location Access Disabled",
message: "In order to work your location settings need to be set to 'Always'.",
preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
let openAction = UIAlertAction(title: "Open Settings", style: .default) { (action) in
if let url = NSURL(string:UIApplicationOpenSettingsURLString) {
UIApplication.shared.open(url as URL)
}
}
alertController.addAction(openAction)
self.present(alertController, animated: true, completion: nil)
}
}
// Location delegate methods
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
// get last location
let location = locations.last
print(location!.coordinate.latitude)
// set region
let region = MKCoordinateRegion(center: location!.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
// deploy region to map
self.mapView.setRegion(region, animated: true)
// Map to follow the user
self.mapView.setUserTrackingMode(MKUserTrackingMode.follow, animated: true)
// Show compass on map
self.mapView.showsCompass = true
// save the location data to CoreData
//self.save(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
// end Location updating
self.LocationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Errors: " + error.localizedDescription)
}
}
My issue is that func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation] calls itself over and over again (around 3 times on initial load)...
I am using the .last which AFAIK is meant to pull out the last result in that object.. which it probably is, as with breakpoints inserted it after the first 2 prints it only returns 1 lot of results...
After searching high and low, I am hoping I can get a result by asking the question... Thanks!
Console output of my issue:
When you call startUpdatingLocation() the location manager immediately starts the delivering of location data. The first incoming locations may be way off your actual location, so check the horizontalAccuracy and verticalAccuracy attributes and dismiss locations which are too inaccurate.
It looks like you just want to get a one-shot location, if so try this code:
// Use:
// at class level:
// var manager: LocationOneShotManager?
// in viewDidLoad:
// manager = LocationOneShotManager()
// manager!.fetchWithCompletion {location, error in
// // fetch location or an error
// if let loc = location {
// println(location)
// } else if let err = error {
// println(err.localizedDescription)
// }
// self.manager = nil
// }
import UIKit
import CoreLocation
// possible errors
enum OneShotLocationManagerErrors: Int {
case AuthorizationDenied
case AuthorizationNotDetermined
case InvalidLocation
}
class LocationOneShotManager: NSObject, CLLocationManagerDelegate {
// location manager
private var locationManager: CLLocationManager?
// destroy the manager
deinit {
locationManager?.delegate = nil
locationManager = nil
}
typealias LocationClosure = ((location: CLLocation?, error: NSError?)->())
private var didComplete: LocationClosure?
// location manager returned, call didcomplete closure
private func _didComplete(location: CLLocation?, error: NSError?) {
locationManager?.stopUpdatingLocation()
didComplete?(location: location, error: error)
locationManager?.delegate = nil
locationManager = nil
}
// location authorization status changed
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .AuthorizedWhenInUse:
self.locationManager!.startUpdatingLocation()
case .Denied:
_didComplete(nil, error: NSError(domain: self.classForCoder.description(),
code: OneShotLocationManagerErrors.AuthorizationDenied.rawValue,
userInfo: nil))
default:
break
}
}
internal func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
_didComplete(nil, error: error)
}
internal func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
_didComplete(location, error: nil)
}
// ask for location permissions, fetch 1 location, and return
func fetchWithCompletion(completion: LocationClosure) {
// store the completion closure
didComplete = completion
// fire the location manager
locationManager = CLLocationManager()
locationManager!.delegate = self
// check for description key and ask permissions
if (NSBundle.mainBundle().objectForInfoDictionaryKey("NSLocationWhenInUseUsageDescription") != nil) {
locationManager!.requestWhenInUseAuthorization()
} else if (NSBundle.mainBundle().objectForInfoDictionaryKey("NSLocationAlwaysUsageDescription") != nil) {
locationManager!.requestAlwaysAuthorization()
} else {
fatalError("To use location in iOS8 you need to define either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in the app bundle's Info.plist file")
}
}
}

How I can center the map on user's location in swift?

I'm writing an app and I have an embedded mapview to show user's his location. This is my code so far:
class YourCurrentLocation: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var locationManager = CLLocationManager()
let regionRadius: CLLocationDistance = 1000
func checkLocationAuthorizationStatus() {
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
mapView.showsUserLocation = true
centerMapOnLocation(locationManager.location!, map: mapView, radius: regionRadius)
} else {
locationManager.requestAlwaysAuthorization() //requestWhenInUseAuthorization()
}
}
func centerMapOnLocation(location: CLLocation, map: MKMapView, radius: CLLocationDistance) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
radius * 2.0, radius * 2.0)
map.setRegion(coordinateRegion, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// mapView.delegate = self
if CLLocationManager.locationServicesEnabled()
{
//locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
print("location enabled")
checkLocationAuthorizationStatus()
}
else
{
print("Location service disabled");
}
// Do any additional setup after loading the view.
}
}
I also added the two entries to my plist:
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
and also in my xcode I have set to emulate the GPS data on london, UK.
When I run the app - I see the map, but london is not marked. What am I doing wrong?
Btw, I had to comment out this line:
//mapView.delegate = self
in viewDidLoad(), otherwise I had the error:
Cannot assign value of type YourCurrentLocation to type MKMapViewDelegate
and I'm not sure if that's a part of the problem here.
I want to achieve the effect when I display to the user map and a point marked on that map with his location. Can you help me with that?
The problem with your code is that you're trying to point the map to the user's location when the user gives location permission, you're not waiting for the CoreLocation to give you the actual user location.
You need to use the CLLocationManagerDelegate method locationManager(_:didUpdateLocations:) to be notified of when you get the user's actual location, and there you can set the map to point to the user's location.
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet var mapView: MKMapView!
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager!.delegate = self
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
locationManager!.startUpdatingLocation()
} else {
locationManager!.requestWhenInUseAuthorization()
}
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .NotDetermined:
print("NotDetermined")
case .Restricted:
print("Restricted")
case .Denied:
print("Denied")
case .AuthorizedAlways:
print("AuthorizedAlways")
case .AuthorizedWhenInUse:
print("AuthorizedWhenInUse")
locationManager!.startUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.first!
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 500, 500)
mapView.setRegion(coordinateRegion, animated: true)
locationManager?.stopUpdatingLocation()
locationManager = nil
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Failed to initialize GPS: ", error.description)
}
}

Resources