首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自CNContactStore requestAccess的错误“承诺不正确地完成”

来自CNContactStore requestAccess的错误“承诺不正确地完成”
EN

Stack Overflow用户
提问于 2019-06-14 23:18:31
回答 2查看 3.1K关注 0票数 0

我正在构建一个UI,以请求对CNContactStore的访问,并处理用户先前(可能是错误地)拒绝访问的情况。当我检测到当前状态是.denied时,我会显示一个UIAlertController,它解释并提议将它们带到应用程序设置以允许访问。

当当前状态为store.requestAccess()时调用.denied时,应用程序崩溃并显示两个错误: 1)“承诺以零错误完成”。2)“承诺不正确地完成了。”调用堆栈如下所示。

我不擅长解释调用堆栈,但我认为错误来自于CNContactStore内部。我不清楚我能做些什么来防止这个错误。

编辑:我没有使用承诺链在我的应用程序。

EDIT2:上面澄清了错误发生在我的代码中的确切位置。

代码语言:javascript
复制
import UIKit
import Contacts
import ContactsUI

final class ContactsAppHelper {

static let shared = ContactsAppHelper()

var store = CNContactStore()

func checkAccessStatus(_ completionHandler: @escaping (_ accessGranted: Bool) -> Void) {

    let authorizationStatus = CNContactStore.authorizationStatus(for: .contacts)

    switch authorizationStatus {
    case .authorized:
        completionHandler(true)
    case .denied, .notDetermined:
        store.requestAccess(for: .contacts, completionHandler: { (access, accessError) -> Void in
            if access {
                completionHandler(access)
            }
            else {
                print("access denied")
                DispatchQueue.main.sync {
                    self.showSettingsAlert(completionHandler)
                }
            }
        })
    default:
        completionHandler(false)
    }
}

private func showSettingsAlert(_ completionHandler: @escaping (_ accessGranted: Bool) -> Void) {

    let msg = "This app requires access to Contacts to proceed. Would you like to open settings and grant permission?"
    let alert = UIAlertController(title: nil, message: msg, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { action in
        completionHandler(false)
        UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
    })
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { action in
        completionHandler(false)
    })
    let vc = UIApplication.getPresentedViewController()
    vc!.present(alert, animated: true)
}
}


extension UIApplication{
class func getPresentedViewController() -> UIViewController? {
    var presentViewController = UIApplication.shared.keyWindow?.rootViewController
    while let pVC = presentViewController?.presentedViewController
    {
        presentViewController = pVC
    }
    return presentViewController
}
}

这些调用堆栈的结果是:

代码语言:javascript
复制
2019-06-14 15:59:12.220116-0700 Sales Networker[805:28798] [Rx] A promise was finished with a nil error.
2019-06-14 15:59:12.226500-0700 Sales Networker[805:28798] [Rx] Call stack: (
    0   ContactsFoundation                  0x000000012242312a -[CNFuture finishWithError:] + 52
    1   Contacts                            0x000000010e0c2a82 __55-[CNDataMapperContactStore requestAccessForEntityType:]_block_invoke_2 + 187
    2   Contacts                            0x000000010e0ffc71 +[CNAuthorization requestAccessForEntityType:completionHandler:] + 77
    3   Contacts                            0x000000010e072c44 -[CNXPCDataMapper requestAccessForEntityType:completionHandler:] + 123
    4   Contacts                            0x000000010e0c299a __55-[CNDataMapperContactStore requestAccessForEntityType:]_block_invoke + 174
    5   libsystem_trace.dylib               0x000000011269cf00 os_activity_apply_f + 66
    6   Contacts                            0x000000010e116d52 -[_CNContactsLogger requestingAccessForContacts:] + 225
    7   Contacts                            0x000000010e0c28a4 -[CNDataMapperContactStore requestAccessForEntityType:] + 177
    8   Contacts                            0x000000010e09b77f -[CNContactStore requestAccessForEntityType:completionHandler:] + 54
    9   Sales Networker                     0x000000010ccaadc7 $s15Sales_Networker17ContactsAppHelperC17checkAccessStatusyyySbcF + 535
    10  Sales Networker                     0x000000010cce9673 $s15Sales_Networker24OnBoardingViewControllerC17rightButtonTappedyySo8UIButtonCF + 451
    11  Sales Networker                     0x000000010cce9ddc $s15Sales_Networker24OnBoardingViewControllerC17rightButtonTappedyySo8UIButtonCFTo + 60
    12  UIKitCore                           0x0000000119c7d204 -[UIApplication sendAction:to:from:forEvent:] + 83
    13  UIKitCore                           0x00000001196d2c19 -[UIControl sendAction:to:forEvent:] + 67
    14  UIKitCore                           0x00000001196d2f36 -[UIControl _sendActionsForEvents:withEvent:] + 450
    15  UIKitCore                           0x00000001196d1eec -[UIControl touchesEnded:withEvent:] + 583
    16  UIKitCore                           0x0000000119cb5eee -[UIWindow _sendTouchesForEvent:] + 2547
    17  UIKitCore                           0x0000000119cb75d2 -[UIWindow sendEvent:] + 4079
    18  UIKitCore                           0x0000000119c95d16 -[UIApplication sendEvent:] + 356
    19  UIKitCore                           0x0000000119d66293 __dispatchPreprocessedEventFromEventQueue + 3232
    20  UIKitCore                           0x0000000119d68bb9 __handleEventQueueInternal + 5911
    21  CoreFoundation                      0x000000010ebd6be1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    22  CoreFoundation                      0x000000010ebd6463 __CFRunLoopDoSources0 + 243
    23  CoreFoundation                      0x000000010ebd0b1f __CFRunLoopRun + 1231
    24  CoreFoundation                      0x000000010ebd0302 CFRunLoopRunSpecific + 626
    25  GraphicsServices                    0x0000000114a702fe GSEventRunModal + 65
    26  UIKitCore                           0x0000000119c7bba2 UIApplicationMain + 140
    27  Sales Networker                     0x000000010cca7f6b main + 75
    28  libdyld.dylib                       0x0000000112416541 start + 1
)
2019-06-14 15:59:12.236494-0700 Sales Networker[805:28798] [Rx] A promise was finished incorrectly.
2019-06-14 15:59:12.236582-0700 Sales Networker[805:28798] [Rx] Result: (null)
2019-06-14 15:59:12.236669-0700 Sales Networker[805:28798] [Rx] Error : (null)
2019-06-14 15:59:12.238150-0700 Sales Networker[805:28798] [Rx] Call stack: (
    0   ContactsFoundation                  0x0000000122422ed8 -[CNFuture finishWithResult:error:] + 290
    1   Contacts                            0x000000010e0c2a82 __55-[CNDataMapperContactStore requestAccessForEntityType:]_block_invoke_2 + 187
    2   Contacts                            0x000000010e0ffc71 +[CNAuthorization requestAccessForEntityType:completionHandler:] + 77
    3   Contacts                            0x000000010e072c44 -[CNXPCDataMapper requestAccessForEntityType:completionHandler:] + 123
    4   Contacts                            0x000000010e0c299a __55-[CNDataMapperContactStore requestAccessForEntityType:]_block_invoke + 174
    5   libsystem_trace.dylib               0x000000011269cf00 os_activity_apply_f + 66
    6   Contacts                            0x000000010e116d52 -[_CNContactsLogger requestingAccessForContacts:] + 225
    7   Contacts                            0x000000010e0c28a4 -[CNDataMapperContactStore requestAccessForEntityType:] + 177
    8   Contacts                            0x000000010e09b77f -[CNContactStore requestAccessForEntityType:completionHandler:] + 54
    9   Sales Networker                     0x000000010ccaadc7 $s15Sales_Networker17ContactsAppHelperC17checkAccessStatusyyySbcF + 535
    10  Sales Networker                     0x000000010cce9673 $s15Sales_Networker24OnBoardingViewControllerC17rightButtonTappedyySo8UIButtonCF + 451
    11  Sales Networker                     0x000000010cce9ddc $s15Sales_Networker24OnBoardingViewControllerC17rightButtonTappedyySo8UIButtonCFTo + 60
    12  UIKitCore                           0x0000000119c7d204 -[UIApplication sendAction:to:from:forEvent:] + 83
    13  UIKitCore                           0x00000001196d2c19 -[UIControl sendAction:to:forEvent:] + 67
    14  UIKitCore                           0x00000001196d2f36 -[UIControl _sendActionsForEvents:withEvent:] + 450
    15  UIKitCore                           0x00000001196d1eec -[UIControl touchesEnded:withEvent:] + 583
    16  UIKitCore                           0x0000000119cb5eee -[UIWindow _sendTouchesForEvent:] + 2547
    17  UIKitCore                           0x0000000119cb75d2 -[UIWindow sendEvent:] + 4079
    18  UIKitCore                           0x0000000119c95d16 -[UIApplication sendEvent:] + 356
    19  UIKitCore                           0x0000000119d66293 __dispatchPreprocessedEventFromEventQueue + 3232
    20  UIKitCore                           0x0000000119d68bb9 __handleEventQueueInternal + 5911
    21  CoreFoundation                      0x000000010ebd6be1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    22  CoreFoundation                      0x000000010ebd6463 __CFRunLoopDoSources0 + 243
    23  CoreFoundation                      0x000000010ebd0b1f __CFRunLoopRun + 1231
    24  CoreFoundation                      0x000000010ebd0302 CFRunLoopRunSpecific + 626
    25  GraphicsServices                    0x0000000114a702fe GSEventRunModal + 65
    26  UIKitCore                           0x0000000119c7bba2 UIApplicationMain + 140
    27  Sales Networker                     0x000000010cca7f6b main + 75
    28  libdyld.dylib                       0x0000000112416541 start + 1
)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-15 01:24:09

我测试了您的代码,发现这里发生了两件事。

第一种情况是,当您在状态已经是requestAccess(for:completion:)时调用.denied时,您将在控制台上得到一个非致命堆栈跟踪。您可以忽略这一点,或者只在.notDetermined状态下请求访问。

第二个问题与主队列上的同步调度有关。由于某种原因导致访问冲突。解决方案是使用异步分派。无论如何,没有好的理由阻止调用队列。

代码语言:javascript
复制
func checkAccessStatus(_ completionHandler: @escaping (_ accessGranted: Bool) -> Void) {

    let authorizationStatus = CNContactStore.authorizationStatus(for: .contacts)

    switch authorizationStatus {
    case .authorized:
        completionHandler(true)
    case .denied:
        self.showSettingsAlert(completionHandler)
    case .notDetermined:
        store.requestAccess(for: .contacts, completionHandler: { (access, accessError) -> Void in
            if access {
                completionHandler(access)
            }
            else {
                print("access denied")
                self.showSettingsAlert(completionHandler)
            }
        })
    default:
        completionHandler(false)
    }
}


private func showSettingsAlert(_ completionHandler: @escaping (_ accessGranted: Bool) -> Void) {

    let msg = "This app requires access to Contacts to proceed. Would you like to open settings and grant permission?"
    let alert = UIAlertController(title: nil, message: msg, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { action in
        completionHandler(false)
        UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
    })
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { action in
        completionHandler(false)
    })
    DispatchQueue.main.async {
        if let vc = UIApplication.getPresentedViewController() {
            vc.present(alert, animated: true)
        } else {
             completionHandler(false)
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2019-08-22 06:32:25

这个错误将在两种情况下出现。

  1. 当您向用户请求联系人权限时,用户拒绝该权限。
  2. 用户授予联系人权限,然后进入settings -> your app > off contact permission

在日志中的这两个场景中,您将看到“一个承诺以零错误完成”。根据客户要求,您可以显示被拒绝的权限警告,也可以忽略它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56606093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档