iOS开发:获取通讯录联系人后正确更新Storyboard UI
问题根因
- 原实现调用
requestAccess发起权限请求后,没有等待用户对权限弹窗做出操作,就立刻切换到主线程查询权限状态执行后续逻辑,此时授权流程还未完成,自然会触发UI提前更新的问题。 CNContactStore的权限请求回调、联系人数据检索逻辑默认运行在子线程,所有UI相关操作必须在主线程执行,直接在回调里调用UI更新方法就会触发主线程校验报错。
修复方案
所有授权判断、后续流程必须放在权限请求的completion回调内触发,确保用户完成授权操作后再执行后续逻辑;所有涉及UI更新、弹窗的操作,手动调度到主线程执行。
基础修复代码如下:
func requestContactsAccess() { let store = CNContactStore() store.requestAccess(for: .contacts) { [weak self] granted, error in guard let self = self else { return } // 统一在主线程执行UI相关逻辑 DispatchQueue.main.async { guard granted, error == nil else { self.alert() return } self.retrieveContacts() self.updateScreen() } } }
如果retrieveContacts包含大量联系人遍历的耗时逻辑,不要把这部分放在主线程执行避免卡顿,调整逻辑如下:
func requestContactsAccess() { let store = CNContactStore() store.requestAccess(for: .contacts) { [weak self] granted, error in guard let self = self else { return } guard granted, error == nil else { DispatchQueue.main.async { self.alert() } return } // 子线程执行耗时的联系人拉取 DispatchQueue.global(qos: .userInitiated).async { self.retrieveContacts() // 拉取完成后切回主线程更新UI DispatchQueue.main.async { self.updateScreen() } } } }
额外注意事项
- 回调内记得使用
[weak self]避免循环引用 retrieveContacts内部需要做好空值、错误处理,比如联系人列表为空的场景下,updateScreen要做对应的兜底展示,不要强制解析首位联系人导致崩溃
内容的提问来源于stack exchange,提问作者David Ott
相关产品推荐
相关产品推荐

