Запрос доступа к контактам в Swift 3

Я хочу получить доступ к контактам пользователя и планирую сделать это, используя контакты и contactsui framework, которые поставляет 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)
    }
}

кто-нибудь может помочь, чтобы попытаться исправить это? Любая помощь будет очень ценится. Спасибо заранее.

Ура, Тео!--3-->

1 ответов


вместо

DispatchQueue.async(group: DispatchQueue.main, execute: { ... }

do

DispatchQueue.main.async { ... }

кстати, если разрешение ранее было отказано, нет смысла запрашивать авторизацию снова, потому что ОС не будет представлять какой-либо пользовательский интерфейс "предоставить доступ" конечному пользователю. Это происходит только в том случае, если пользователь ранее не отказывал в доступе.

Если доступ к контактам действительно необходим для успешной работы приложения, вы можете показать им предупреждение, которое дает им возможность перейти к настройкам прямо из вашего приложения:

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)
}