赋值非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
相关产品推荐
相关产品推荐

