我想访问用户的联系人,并打算使用Apple提供的联系人和联系人框架。
首先,我需要征求权限以访问用户的联系人,并且难以这样做。在Swift 2中,人们可以要求这样的许可:
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)nnPlease allow the app to access your contacts through the Settings."
self.showMessage(message)
})
}
}
})
default:
completionHandler(accessGranted: false)
}
}
我试图像这样将其转换为Swift 3,但仍提出错误。错误是"实例成员'async'不能在类型的'dispatchqueue'上使用;您的意思是使用这种类型的值吗?":
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)nnPlease allow the app to access your contacts through the Settings."
self.showMessage(message)
})
}
}
})
default:
completionHandler(false)
}
}
任何人可以帮助尝试解决这个问题吗?任何帮助将不胜感激。提前一吨。
欢呼,theo
而不是
DispatchQueue.async(group: DispatchQueue.main, execute: { ... }
做
DispatchQueue.main.async { ... }
顺便说一句,如果以前已拒绝了权限,则再次请求授权是没有意义的,因为OS不会向最终用户提供任何"授予访问" UI。仅当用户以前没有拒绝访问时才这样做。
如果对该应用程序成功操作确实至关重要,则可以向他们展示一个警报,使他们可以直接从您的应用程序进行设置:
: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)
}
同样的事情,但它将否视为 no ,而不是现在或类似的东西。您在Apple隐私提示中看到了任何模糊逻辑吗?我没有。
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)
}
}