请求访问Swift中的联系人3

The*_*uss 11 contacts ios swift swift3

我想访问用户的联系人,并计划使用Apple提供的Contacts和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)
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试将它转换为Swift 3,但仍然会出现错误.错误是"实例成员'异步'不能在类型'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)\n\nPlease allow the app to access your contacts through the Settings."
                        self.showMessage(message)
                    })
                }
            }
        })

    default:
        completionHandler(false)
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮忙解决这个问题吗?任何帮助都会非常感激.非常感谢提前.

干杯,西奥

Rob*_*Rob 29

代替

DispatchQueue.async(group: DispatchQueue.main, execute: { ... }
Run Code Online (Sandbox Code Playgroud)

DispatchQueue.main.async { ... }
Run Code Online (Sandbox Code Playgroud)

顺便说一下,如果先前已经拒绝了许可,则再次请求授权是没有意义的,因为操作系统不会向最终用户提供任何"授权访问"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. 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)
}
Run Code Online (Sandbox Code Playgroud)