Ios 请求访问Swift 3中的联系人

Ios 请求访问Swift 3中的联系人,ios,swift,swift3,contacts,Ios,Swift,Swift3,Contacts,我想访问用户的联系人,并计划使用苹果提供的联系人和联系人框架 不过,首先,我需要获得访问用户联系人的权限,但我在这样做时遇到了麻烦。在Swift 2中,可以这样请求许可: func requestForAccess(completionHandler: (accessGranted: Bool) -> Void) { let authorizationStatus = CNContactStore.authorizationStatusForEntityType(CNEntityT

我想访问用户的联系人,并计划使用苹果提供的联系人和联系人框架

不过,首先,我需要获得访问用户联系人的权限,但我在这样做时遇到了麻烦。在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,但还是出现了错误。错误为“实例成员'async'不能用于'DispatchQueue'类型;是否改为使用此类型的值?”:

有人能帮忙解决这个问题吗?任何帮助都将不胜感激。非常感谢

干杯, Theo

代替

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


顺便说一句,如果之前权限被拒绝,那么再次请求授权就没有意义了,因为操作系统不会向最终用户提供任何“授予访问权”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)
    }
}

“我仍然会犯错误”不是一个问题。清楚地说出“错误”是什么以及在哪一行。另外,您真的认为在堆栈溢出之前,没有人讨论过如何在Swift 3中授权联系人访问吗?在询问之前尝试搜索。节省带宽。@matt我认为堆栈溢出不需要这种攻击。我加上了错误,但还是冷静了下来out@GIJOW上面加的。“实例成员'async'不能在'DispatchQueue'类型上使用;您的意思是使用此类型的值吗?”非常感谢!您是否建议删除我拥有的整个函数,并将其替换为此函数?或者在上面添加showFunctionsAlert()。我不确定是否理解您的问题。但是这会请求访问,如果被拒绝,还会显示警报,所以我不确定您还需要什么。顺便说一下,我调整了我的答案,以使用闭包参数,就像您最初的示例一样。我最初的示例是在视图出现时请求授权,但最好将此问题推迟到用户真正需要访问的时候(可能是当视图出现时,但更可能的是,当他们点击某些明显需要联系人的内容时;如果您将其推迟到最新的可能时刻,则用户更有可能参与您的应用程序并授予权限。嘿,抱歉,在我看到您的编辑之前发表了评论。我在问我是否应该将我拥有的功能包括在我的i第一个问题和上面的两个功能。或者,您在回答中提供的功能是否足以请求用户许可。非常感谢所有帮助,我现在明白了您的目标。我正准备单击复选标记,但还有一个问题。我应该在viewdidload中调用这两个功能,还是不需要。t汉克斯一吨
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)
    }
}