In my app I have a tab called \"Discover\". The Discover tab will use the users current location to find \"stuff\" near them. Instead of presenting the user with a generic Autho
This solution isn't the best in all scenarios, but it worked for me so I thought I'd share:
import Foundation
import CoreLocation
class LocationManager: NSObject, CLLocationManagerDelegate {
static let sharedInstance = LocationManager()
private var locationManager = CLLocationManager()
private let operationQueue = OperationQueue()
override init(){
super.init()
//Pause the operation queue because
// we don't know if we have location permissions yet
operationQueue.isSuspended = true
locationManager.delegate = self
}
///When the user presses the allow/don't allow buttons on the popup dialogue
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
//If we're authorized to use location services, run all operations in the queue
// otherwise if we were denied access, cancel the operations
if(status == .authorizedAlways || status == .authorizedWhenInUse){
self.operationQueue.isSuspended = false
}else if(status == .denied){
self.operationQueue.cancelAllOperations()
}
}
///Checks the status of the location permission
/// and adds the callback block to the queue to run when finished checking
/// NOTE: Anything done in the UI should be enclosed in `DispatchQueue.main.async {}`
func runLocationBlock(callback: @escaping () -> ()){
//Get the current authorization status
let authState = CLLocationManager.authorizationStatus()
//If we have permissions, start executing the commands immediately
// otherwise request permission
if(authState == .authorizedAlways || authState == .authorizedWhenInUse){
self.operationQueue.isSuspended = false
}else{
//Request permission
locationManager.requestAlwaysAuthorization()
}
//Create a closure with the callback function so we can add it to the operationQueue
let block = { callback() }
//Add block to the queue to be executed asynchronously
self.operationQueue.addOperation(block)
}
}
Now every time you want to use location information, just surround it with this:
LocationManager.sharedInstance.runLocationBlock {
//insert location code here
}
So whenever you try using the location information, the authorization status is checked. If you don't have permission yet, it requests permission and waits until the user presses the "Allow" button or the "Don't allow" button. If the "Allow" button is pressed, any requests for location data will be processed on separate threads, but if the "Don't Allow" button is pressed, all location requests will be canceled.