Request Access To Contacts in Swift 3
Same thing, really but it treats no as a no, as opposed to maybe, not now or anything like that. Did you see any fuzzy logic in Apple privacy prompts? I did not.
fileprivate func requestForAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void) {
let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts)
switch authorizationStatus {
case .authorized:
completionHandler(true)
case .notDetermined:
self.contactStore.requestAccess(for: CNEntityType.contacts, completionHandler: { (access, accessError) -> Void in
if access {
completionHandler(access)
}
else {
completionHandler(false)
}
})
default:
completionHandler(false)
}
}
Instead of
DispatchQueue.async(group: DispatchQueue.main, execute: { ... }
do
DispatchQueue.main.async { ... }
By the way, if permission had previously been denied, there's no point in requesting authorization again, because the OS will not present any "grant access" UI to the end user. It only does that if the user had not previously denied access.
If access to Contacts is truly essential for successful operation of the app, you can show them an alert that gives them the option of going to Settings directly from your app:
func requestAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void) {
switch CNContactStore.authorizationStatus(for: .contacts) {
case .authorized:
completionHandler(true)
case .denied:
showSettingsAlert(completionHandler)
case .restricted, .notDetermined:
store.requestAccess(for: .contacts) { granted, error in
if granted {
completionHandler(true)
} else {
DispatchQueue.main.async {
self.showSettingsAlert(completionHandler)
}
}
}
}
}
private func showSettingsAlert(_ completionHandler: @escaping (_ accessGranted: Bool) -> Void) {
let alert = UIAlertController(title: nil, message: "This app requires access to Contacts to proceed. Go to Settings to grant access.", preferredStyle: .alert)
if
let settings = URL(string: UIApplication.openSettingsURLString),
UIApplication.shared.canOpenURL(settings) {
alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { action in
completionHandler(false)
UIApplication.shared.open(settings)
})
}
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { action in
completionHandler(false)
})
present(alert, animated: true)
}