You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用CNContactViewController(forUnknownContact)致视图控制器层级异常问题

问题分析与解决方案

这确实是个容易踩坑的场景,但大概率不是Apple的Bug,而是CNContactViewController不同初始化方法的预期行为差异导致的问题。

核心差异点

  • CNContactViewController(forNewContact:)的设计定位是让用户创建全新联系人,整个流程的交互完全由开发者和用户主导,所以允许自定义工具栏、导航栏等元素,不会有内部逻辑冲突。
  • CNContactViewController(forUnknownContact:)的作用是展示未知联系人的信息,并提供“添加到通讯录”这类系统预设的交互,它的内部已经对工具栏做了固定布局和逻辑绑定。你强行替换工具栏的items,会打乱它的内部视图层级和交互逻辑,最终导致崩溃。

正确的实现方式

如果需要给这个联系人页面添加关闭按钮,应该把按钮加到导航栏,而不是修改工具栏。示例代码如下:

func openVCard(for cnContact: CNContact) {
    let contactViewController = CNContactViewController(forUnknownContact: cnContact)
    contactViewController.contactStore = CNContactStore()
    contactViewController.delegate = self
    
    let navigationController = UINavigationController(rootViewController: contactViewController)
    
    // 将Close按钮添加到导航栏右侧
    contactViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(
        title: "Close",
        style: .done,
        target: self,
        action: #selector(closeContactViewController)
    )
    
    // 保持工具栏隐藏,使用系统默认的布局
    navigationController.isToolbarHidden = true
    contactViewController.edgesForExtendedLayout = []
    
    present(navigationController, animated: true, completion: nil)
}

@objc private func closeContactViewController() {
    dismiss(animated: true, completion: nil)
}

额外说明

如果你需要自定义更多交互,也可以考虑自己实现一个联系人展示页面,完全控制视图层级和逻辑,避免依赖系统控制器的潜在限制。

内容的提问来源于stack exchange,提问作者Vyacheslav

火山引擎 最新活动