访问用户地址簿的权限警报不会停止执行

Permission alert to access user's address book does not halt execution

我有一个按钮可以从用户的地址簿中导入联系人。当他们第一次点击按钮时,我的代码 return 是一个布尔值,指示用户是否已授予权限。如果授予权限,则导入联系人,然后我执行转至 table 视图。如果未授予权限,则不会导入联系人,我对空 table 视图执行相同的 segue。这是我拥有的:

func myImportThenSegueFunction() {
    if userHasAuthorizedAddressBookAccess() == true {
        // Import contacts and perform segue
    } else {
        // Just perform segue
    }
}

func userHasAuthorizedAddressBookAccess() -> Bool {
    switch ABAddressBookGetAuthorizationStatus() {
    case .Authorized:
        return true
    case .NotDetermined:
        var userDidAuthorize: Bool!
        ABAddressBookRequestAccessWithCompletion(nil) { (granted: Bool, error: CFError!) in
            if granted {
                userDidAuthorize = true
            } else {
                userDidAuthorize = false
            }
        }
        return userDidAuthorize
    case .Restricted:
        return false
    case .Denied:
        return false
    }
}

问题在于,当点击按钮时,会短暂显示访问设置警报的权限,而在后台,视图会在用户在警报提示中授予或拒绝访问权限之前执行 segue。然后应用程序立即崩溃说 .NotDetermined returned nil 意味着变量 userDidAuthorize returned 在用户甚至可以选择设置 userDidAuthorize 在 if/else 块中 ABAddressBookRequestAccessWithCompletion(nil).

我的问题是,为什么在用户通过警报提示将变量 userDidAuthorize 设置为 return 之前,代码会在 .NotDetermined 的情况下执行 return ?我已经看到一些 hacks 来延迟执行,我知道这个功能已被弃用。我怎样才能让它正常工作?

因为ABAddressBookRequestAccessWithCompletion是异步的,returns是立即的。它需要像这样,因为它通常在主线程中使用,并且在请求用户许可时不能阻塞。

你需要改变你使用它的方式来接受这个,一旦你知道状态就调用一个完成块而不是立即返回状态。