Location permission check and authorization - ios

I want my program to display the users location on the map. It was working at first then randomly stopped so i added the code below to try to fix it but I'm having problems. Thanks in advance!
override func viewDidLoad()
{
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
if CLLocationManager.locationServicesEnabled()
{
let status: CLAuthorizationStatus = CLLocationManager.authorizationStatus()
if status == CLAuthorizationStatus.NotDetermined
{
locationManager.requestAlwaysAuthorization()
}
} else {
print("locationServices disenabled")
}
locationManager.startUpdatingLocation()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
mapView.delegate = self
centerMapOnLocation(initialLocation)
addBoundry()
}

You required to call,
locationManager.requestAlwaysAuthorization()
as well
locationManager.requestWhenInUseAuthorization()
to use location smoothly in foreground also!!!
and you should not need two instance to call startupdatinglocation. keep one. you should use instance or global variable instead of local to get location throughout the scope.
Update :
You have to set two keys in info.plist like, NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription with it's usage description.

If you want the "WhenInUse" notification you should only add "Privacy - Location When In Use Usage Description" in your info.plist but if you want the "Always" access your info.plist should look like this info.plist screenshot:
You don't have to add any request authorization like requestAlwaysAuthorization or requestWhenInUseAuthorization

I was having the same issue, even with NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescriptionset in info.plist. My debugger told me to also set NSLocationAlwaysAndWhenInUseUsageDescription...so I did it. It worked!

This is my code:
First import the library:
import CoreLocation
A little example:
let status: CLAuthorizationStatus = CLLocationManager.authorizationStatus()
if status == CLAuthorizationStatus.notDetermined || status == CLAuthorizationStatus.denied || status == CLAuthorizationStatus.restricted
{
locationManager?.requestAlwaysAuthorization()
}
And don`t forget to add these permissions in the Info.plist:

Related

Get precise location every 1 minute in iOS 14

I am working on concept of guard application where in i need guard actual location every 60 seconds. same functionality was working in iOS 12, but in iOS 13 and 14 not working as it should be. i have made below changes for location manager.
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.distanceFilter = 2
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.activityType = .other
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
am getting precise location when app is in foreground, but as soon as app goes background am not getting actual location. it would be great if any one can help me out as its causing the productivity of app and its basic usage.
Request the requestAlwaysAuthorization, if you are going to use the user’s location in the background.
let authorizationStatus = CLLocationManager.authorizationStatus()
if authorizationStatus == .authorizedAlways {
locationManager.startMonitoringSignificantLocationChanges()
} else {
locationManager.requestAlwaysAuthorization()
}
And also update the Info.plist:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
Please, make sure to read the documentation first.
Apart from setting the allowsBackgroundLocationUpdates to true, you also need to check the “Location updates” capability for your app in Xcode.
When a location update occurs while your app is in the background, the system launches your app and passes an options dictionary to the application(:willFinishLaunchingWithOptions:) or application(:didFinishLaunchingWithOptions:) methods. The dictionary may contain the location key to indicate that location services caused the app to launch.

Rotate SCNNode to North without permission for location tracking

We would like to rotate a SCNNode so as to match with the North direction.
Arkit allows to align its z-axis with the North but this requires user permission for location tracking, and we don't want to ask for it.
see gravityandheading
As a consequence, we're trying to use the magnetic field property of CMDeviceMotion. But we have no idea how to do that.
There are probably some matrix calculations, but we don't master them for the time being.
see magneticfield
Any help would be highly appreciated! thanks!
You cannot use Location Tracking without user's permission.
Here are some tips on how to setup it properly for AR apps and NON-AR apps:
In iOS 11 and higher here's what you need to do to get location working:
Add a key to your info.plist and request authorisation from the location manager asking it to start. There are two Property List Keys in info.plist for the location authorisation. One or both of these keys is required. In NON-AR apps if neither of the keys are there, you can call startUpdatingLocation method but the location manager won’t actually start. It won’t send a failure message to the delegate either (since it never started, it can’t fail). It will also fail if you add one or both of the keys but forget to explicitly request authorisation.
Use these two Property List Keys in info.plist file. They are used since iOS 11 was released:
<key>NSLocationWhenInUseUsageDescription</key>
<string>App needs an access to your location (in foreground)</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>App needs an access to your location (in background)</string>
And these two Property List Keys were deprecated earlier (DON'T USE THESE KEYS):
<key>NSLocationUsageDescription</key>
<string>App needs an access to your location (in background)</string>
<key>NSLocationAlwaysUsageDescription</key>
<true/>
Here's how your code for AR apps should look like:
let configuration = ARWorldTrackingConfiguration()
func session(_ session: ARSession, didFailWithError error: Error) {
switch error.code {
case 101:
configuration.worldAlignment = .gravity
restartSession()
default:
configuration.worldAlignment = .gravityAndHeading
restartSession()
}
}
func restartSession() {
self.sceneView.session.pause()
self.sceneView.session.run(configuration,
options: [.resetTracking, .removeExistingAnchors])
}
For NON-AR apps use these two instance methods: requestAlwaysAuthorization() (requests permission to use location services whenever the app is running) and requestWhenInUseAuthorization() (requests permission to use location services while the app is in the foreground).
Here's how your code for NON-AR apps should look like:
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
func updateMyLocation() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
if locationManager.respondsToSelector(#selector(CLLocationManager.requestWhenInUseAuthorization)) {
locationManager.requestWhenInUseAuthorization()
} else {
locationManager.startUpdatingLocation()
}
}
}
Also, you can request Always Authorization:
let locationManager = CLLocationManager()
func enableLocationServices() {
locationManager.delegate = self
switch CLLocationManager.authorizationStatus() {
case .notDetermined:
// Request when-in-use authorization initially
locationManager.requestWhenInUseAuthorization()
break
case .restricted, .denied:
// Disable location features
disableMyLocationBasedFeatures()
break
case .authorizedWhenInUse:
// Enable basic location features
enableMyWhenInUseFeatures()
break
case .authorizedAlways:
// Enable any of your app's location features
enableMyAlwaysFeatures()
break
}
}
Hope this helps.

What's the proper way to use startMonitoringSignificantLocationChanges in swift 4?

I try to make a running app, and I want to use the method startMonitoringSignificantLocationChanges, but I'm missing something because is not firing the didUpdateLocations that the documentation says it should.
I have successfully used the startUpdatingLocation method of the CLLocationManager class and I can totally can use it for my interests, but I'd like to understand why my implementation doesn't work.
So, I have this code:
let locationManager = CLLocationManager()
func determineMyCurrentLocation() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
print("authorization Status: \(CLLocationManager.authorizationStatus().rawValue)")
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation() //(1)
//(2)locationManager.startMonitoringSignificantLocationChanges()
locationManager.distanceFilter = 20
//locationManager.start
//locationManager.startUpdatingHeading)(
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { print("yaaay!") }
If you comment (1) and uncomment 2 the func locationManager...etc is never fired.
Also, I have my info.plist with the proper keys set, "Privacy - Location When In Use Usage Description" and "Privacy - Location Always and When In Use Usage Description").
Any idea?
Thanks in advance.
EDITED: My question was imprecise. I put the locationManager property as a class member and I completed the properties in my info.plist
The startMonitoringSignificantLocationChanges requires always authorisation. That also means you should turn on "Background Modes" in Capabilities section and selection "Location Updates". You also require the Privacy - Location Always Usage Description Try these two and you should receive significant location change updates.

Unable to get the permission prompt from CLLocationManager

Here is my code from a ViewController implementing CLLocationManagerDelegate:
func startLocationManager() {
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
println("I'm called")
locationManager.requestAlwaysAuthorization()
// locationManager.startMonitoringSignificantLocationChanges()
locationManager.startUpdatingLocation()
let status = CLLocationManager.authorizationStatus()
println(status.rawValue) // This print 0 which stands for kCLAuthorizationStatusNotDetermined
println(CLLocationManager.locationServicesEnabled()) // true
}
func locationManager(manager: CLLocationManager!,
didUpdateLocations locations: [AnyObject]!) {
println("nobody call me ever, and I'm sad")
}
For some reason, I never get the prompt / alter to autorise location updates. I have tried on my device iOS 8.1 and the simulartor. I followed the advices found here: requestAlwaysAuthorization not showing permission alert :
"Add Core Location framework to Project Settings / Targets / Capabilities / Background Modes set "Location Updates" and "Uses Bluetooth LE Accessories" Add key at Info.plist NSLocationAlwaysUsageDescription".
I have also tried to clean up and rebuild, nothing change. I feel clueless.
EDIT: This question seems related: iOS: App is not asking user's permission while installing the app. getting kCLAuthorizationStatusNotDetermined every time - Objective-c & Swift but the selected answer and its article doesn't expose anything new
Your CLLocationManager object is local object and thus will be deallocated immediately after it falls out of scope. Make it a class property and then asynchronous processes like requesting authorization and determining the location will have a chance to run.

CoreLocation Authorization issues - never prompted for authorization

I was testing out CoreLocation to learn how to capture and record the location of the user. I built a simple Master-Detail app which, in the detail pane, showed the user's live location. Everything worked as expected.
Next, I moved on to making my real app which also uses CoreLocation. I built the app with a Master-Detail style and also made it so that when the user opens the detail pane, it should show their current, live, location. However, nothing happens at all.
What I determined after a LOT of debugging and research is that as soon as my locationManager is created and I call locationManager.startUpdatingLocation() the authorization to get the location is changed to denied (or false, or whatever its called). The only way I can get live tracking is build and run the app in Xcode, once it opens in the simulator, open up Location Services and change the app setting to allow location tracking to "Always". Then I can see in the console that locations are being acquired.
I don't understand why I have to keep changing the authorization to "Always" over and over. I have deleted the app on the simulator, done a "clean" from XCode to start fresh, and still it starts on the simulator without authorization.
Anyone have ideas?
UPDATE Now I see that, when I build and it runs in the simulator, I get ONE location, then the authorization is changed to not allow location services.
Here's my code (which worked on another app):
import UIKit
import CoreLocation
class DetailViewController: UIViewController, CLLocationManagerDelegate {
var locationManager : CLLocationManager!
func startTrackingLocation() {
println("tracking engaged")
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization() // <-- this was originally commented out
locationManager.startUpdatingLocation()
println("and we're tracking")
println(locationManager.location)
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
println("location acquired") // <--- Only see this when I manually allow location when app is running
self.newLongLabel?.text = "\(locations[0].coordinate.longitude)"
self.newLatLabel?.text = "\(locations[0].coordinate.latitude)"
}
override func viewDidLoad() {
super.viewDidLoad()
self.startTrackingLocation()
self.configureView()
}
// more class stuff...
If you're certain you have added the key to plist file try checking for it in the didChangeAuthorizationStatus: location manager delegate method.
Be sure you have both keys in plist as type string and with the values you would like to display to the user:
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
- (void) locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways){
if ([CLLocationManager locationServicesEnabled]) {
[yourLocationManager startMonitoringSignificantLocationChanges];
//run your code here
}
}
}

Resources