swiftswiftuicncontactstoreios-contacts

Change view once contact permission is granted


At the moment, I am able to successfully ask the user for their permission to access their Contact information. I am handling this through a switch statement like so:

func requestContactPermissions() {
    let store = CNContactStore()
    var authStatus = CNContactStore.authorizationStatus(for: .contacts)
    switch authStatus {
    case .restricted:
        print("User cannot grant permission, e.g. parental controls in force.")
        exit(1)
    case .denied:
        print("User has explicitly denied permission.")
        print("They have to grant it via Preferences app if they change their mind.")
        exit(1)
    case .notDetermined:
        print("You need to request authorization via the API now.")
        store.requestAccess(for: .contacts) { success, error in
            if let error = error {
                print("Not authorized to access contacts. Error = \(String(describing: error))")
                exit(1)
            }

            if success {
                print("Access granted")
            }
        }
    case .authorized:
        print("You are already authorized.")
    @unknown default:
        print("unknown case")
    }
}

In the .notDetermined case, this is opening the dialog where I can either click no or yes, granting or denying the application access. This is fine and expected.

What I am looking to do, is change the view if the user clicks yes. Right now, I have the requestContactPermissions function within a button like so:

Button(action: {
    withAnimation {
        // TODO: Screen should not change until access is successfully given.
        requestContactPermissions()
        // This is where the view change is occurring.
        self.loginSignupScreen = .findFriendsResults
    }
}) 

How might I add in the logic to have the view change once the user has granted the application access to their contacts?


Solution

  • add a completion to the requestContactPermissions function something like this (I trimmed the irrelevant parts for the answer):

    func requestContactPermissions(completion: @escaping (Bool) -> ()) {
        let store = CNContactStore()
        var authStatus = CNContactStore.authorizationStatus(for: .contacts)
        switch authStatus {
        case .notDetermined:
           print("You need to request authorization via the API now.")
           store.requestAccess(for: .contacts) { success, error in
              if let error = error {
                 print("Not authorized to access contacts. Error = \(String(describing: error))")
                exit(1)
                //call completion for failure
                completion(false)
              }
    
              if success {
                //call completion for success
                completion(true)
                print("Access granted")
              }
          }
       }
    }
    

    and then you can determine inside the closure whether the user granted permission or not:

    Button(action: {
      withAnimation {
        // TODO: Screen should not change until access is successfully given.
        requestContactPermissions { didGrantPermission in
    
           if didGrantPermission {
              //this is the part where you know if the user granted permission:
              // This is where the view change is occurring.
              self.loginSignupScreen = .findFriendsResults
           }
        }
    
      }
    })