Je souhaite accéder aux contacts de l'utilisateur et je prévois de le faire en utilisant le cadre Contacts et ContactsUI fourni Apple fournitures.
Cependant, je dois d'abord demander la permission d'accéder aux contacts de l'utilisateur et j'ai du mal à le faire. Dans Swift 2, on pourrait demander la permission comme ceci:
func requestForAccess(completionHandler: (accessGranted: Bool) -> Void) {
let authorizationStatus = CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts)
switch authorizationStatus {
case .Authorized:
completionHandler(accessGranted: true)
case .Denied, .NotDetermined:
self.contactStore.requestAccessForEntityType(CNEntityType.Contacts, completionHandler: { (access, accessError) -> Void in
if access {
completionHandler(accessGranted: access)
}
else {
if authorizationStatus == CNAuthorizationStatus.Denied {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let message = "\(accessError!.localizedDescription)\n\nPlease allow the app to access your contacts through the Settings."
self.showMessage(message)
})
}
}
})
default:
completionHandler(accessGranted: false)
}
}
J'ai essayé de le convertir en Swift 3 comme ça, mais je rencontre toujours des erreurs. L'erreur est "Le membre d'instance 'async' ne peut pas être utilisé sur le type 'DispatchQueue'; vouliez-vous utiliser une valeur de ce type à la place? ":
func requestForAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void) {
let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts)
switch authorizationStatus {
case .authorized:
completionHandler(true)
case .denied, .notDetermined:
self.contactStore.requestAccess(for: CNEntityType.contacts, completionHandler: { (access, accessError) -> Void in
if access {
completionHandler(access)
}
else {
if authorizationStatus == CNAuthorizationStatus.denied {
DispatchQueue.async(group: DispatchQueue.main, execute: { () -> Void in //error here
let message = "\(accessError!.localizedDescription)\n\nPlease allow the app to access your contacts through the Settings."
self.showMessage(message)
})
}
}
})
default:
completionHandler(false)
}
}
Quelqu'un peut-il aider à résoudre ce problème? Toute aide serait grandement appréciée. Merci une tonne à l'avance.
À la vôtre, Theo
Au lieu de
DispatchQueue.async(group: DispatchQueue.main, execute: { ... }
faire
DispatchQueue.main.async { ... }
Soit dit en passant, si l'autorisation avait déjà été refusée, il est inutile de demander à nouveau l'autorisation, car le système d'exploitation ne présentera aucune interface utilisateur "d'accorder l'accès" à l'utilisateur final. Il ne le fait que si l'utilisateur n'a pas précédemment refusé l'accès.
Si l'accès aux contacts est vraiment essentiel au bon fonctionnement de l'application, vous pouvez leur montrer une alerte qui leur donne la possibilité d'accéder aux paramètres directement depuis votre application:
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. Would you like to open settings and grant permission to contacts?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { action in
completionHandler(false)
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!)
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { action in
completionHandler(false)
})
present(alert, animated: true)
}