请求访问 Swift 中的联系人 3
Request Access To Contacts in Swift 3
我想访问用户的通讯录,并计划使用 Apple 提供的通讯录和 ContactsUI 框架。
不过,首先,我需要获得访问用户联系人的权限,但在这样做时遇到了问题。在 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)\n\nPlease allow the app to access your contacts through the Settings."
self.showMessage(message)
})
}
}
})
default:
completionHandler(accessGranted: false)
}
}
我试着像这样将它转换为 Swift 3,但我仍然遇到错误。错误是 "Instance member 'async' cannot be used on type 'DispatchQueue'; did you mean to use a value of this type instead?":
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)
}
}
谁能帮忙解决这个问题?任何帮助将不胜感激。提前致谢。
干杯,
西奥
而不是
DispatchQueue.async(group: DispatchQueue.main, execute: { ... }
做
DispatchQueue.main.async { ... }
顺便说一句,如果权限之前已被拒绝,则无需再次请求授权,因为 OS 不会向最终用户显示任何 "grant access" 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)
}
同样的事情,真的,但它将否视为 否,而不是可能,现在不是或类似的东西。你有没有看到苹果隐私提示中有什么模糊的逻辑?我没有。
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)
}
}
我想访问用户的通讯录,并计划使用 Apple 提供的通讯录和 ContactsUI 框架。
不过,首先,我需要获得访问用户联系人的权限,但在这样做时遇到了问题。在 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)\n\nPlease allow the app to access your contacts through the Settings."
self.showMessage(message)
})
}
}
})
default:
completionHandler(accessGranted: false)
}
}
我试着像这样将它转换为 Swift 3,但我仍然遇到错误。错误是 "Instance member 'async' cannot be used on type 'DispatchQueue'; did you mean to use a value of this type instead?":
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)
}
}
谁能帮忙解决这个问题?任何帮助将不胜感激。提前致谢。
干杯, 西奥
而不是
DispatchQueue.async(group: DispatchQueue.main, execute: { ... }
做
DispatchQueue.main.async { ... }
顺便说一句,如果权限之前已被拒绝,则无需再次请求授权,因为 OS 不会向最终用户显示任何 "grant access" 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)
}
同样的事情,真的,但它将否视为 否,而不是可能,现在不是或类似的东西。你有没有看到苹果隐私提示中有什么模糊的逻辑?我没有。
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)
}
}