CLLocationManager AuthorizationStatus callback?

后端 未结 6 1826
天命终不由人
天命终不由人 2021-02-01 02:38

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

6条回答
  •  伪装坚强ぢ
    2021-02-01 03:14

    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.

提交回复
热议问题