You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

赋值非nil的cell给popoverPresentationController.sourceView后仍为nil的问题

为什么设置popoverPresentationController的sourceView后仍为nil?

你遇到的问题核心是设置popoverPresentationController相关属性的顺序完全搞反了!

UIPopoverPresentationController并不是一开始就存在的——只有当你把视图控制器的modalPresentationStyle设置为.popover之后,系统才会自动创建这个控制器实例并赋值给popoverPresentationController属性。你现在的代码是先尝试给popOverVC.popoverPresentationController?.sourceView赋值,这时候这个popoverPresentationController还是nil,所有基于可选链的赋值操作根本不会生效。

修复后的完整代码

@IBAction func selectParValue(_ sender: UIButton) {
    // 获取包含选中按钮的cell
    guard let cell = sender.superview?.superview as? HoleTableViewCell else { return }
    let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "parPopover")
    
    // 第一步:先设置modalPresentationStyle,触发popoverPresentationController的创建
    popOverVC.modalPresentationStyle = .popover
    
    print("Cell number " + String(describing: cell) + " selected")
    // 现在popoverPresentationController已经存在,可以正常赋值了
    popOverVC.popoverPresentationController?.sourceView = cell
    print(String(describing: popOverVC.popoverPresentationController?.sourceView))
    
    popOverVC.popoverPresentationController?.sourceRect = cell.bounds
    popOverVC.popoverPresentationController!.delegate = self
    present(popOverVC, animated: true, completion: nil)
}

原理补充

普通的UIViewController默认没有popoverPresentationController,这个属性只有在你指定了需要以popover形式展示(即设置modalPresentationStyle = .popover)时,系统才会为其生成对应的控制器实例。你之前的代码顺序相当于在“还没创建控制器”的时候就去给它的属性赋值,自然不会有任何效果,这也是为什么第二次打印输出nil,最终导致崩溃的原因。

调整顺序后,先让系统创建出popoverPresentationController,再设置sourceView、sourceRect等属性,就能正常触发popover的展示了。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:46:47