如何在WKWebView Popover显示时保持SCNView响应并仅通过铃铛按钮关闭?
解决方案
1. 让SCNView在Popover显示时保持响应
默认情况下,UIPopoverPresentationController会拦截背后视图的所有交互,我们只需要通过passthroughViews属性,把你的scnView加入到允许穿透交互的视图列表里,就能让SCNView的相机控制手势正常工作了。
修改你的onBellBtnPressed方法,添加这一行代码:
myWebViewVC.popoverPresentationController?.passthroughViews = [scnView]
2. 仅允许点击铃铛按钮关闭Popover
默认的Popover行为是点击外部区域自动关闭,要改这个逻辑,我们需要实现UIPopoverPresentationControllerDelegate的相关方法,同时自己管理Popover的显示状态:
第一步:添加状态跟踪变量
在MainVC里新增一个属性,用来记录Popover是否处于显示状态:
var isPopoverPresented = false
第二步:修改铃铛按钮的点击逻辑
点击按钮时,如果Popover已经显示就关闭它,否则弹出它:
@IBAction func onBellBtnPressed(_ sender: UIButton) { if isPopoverPresented { // 关闭Popover并更新状态 dismiss(animated: true) { self.isPopoverPresented = false } return } // 弹出Popover的逻辑 myWebViewVC.modalPresentationStyle = .popover myWebViewVC.popoverPresentationController?.delegate = self myWebViewVC.popoverPresentationController?.sourceView = sender myWebViewVC.popoverPresentationController?.sourceRect = sender.bounds // 允许SCNView穿透交互 myWebViewVC.popoverPresentationController?.passthroughViews = [scnView] present(myWebViewVC, animated: true) { self.isPopoverPresented = true } }
第三步:实现代理方法阻止默认关闭行为
添加两个代理方法,一个阻止外部点击关闭,另一个确保状态变量在Popover意外关闭时同步更新:
// 阻止点击外部区域关闭Popover func popoverPresentationControllerShouldDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) -> Bool { return false } // Popover被关闭时更新状态变量 func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) { isPopoverPresented = false }
完整修改后的MainVC代码
class MainVC: UIViewController, UIPopoverPresentationControllerDelegate { @IBOutlet weak var scnView: SCNView! @IBOutlet weak var bellBtn: UIButton! var myWebViewVC: MyWebViewVC! var isPopoverPresented = false // 跟踪Popover显示状态 override func viewDidLoad() { super.viewDidLoad() let scene = SCNScene(named: "art.scnassets/DemoScene.scn")! scnView.scene = scene scnView.allowsCameraControl = true } @IBAction func onBellBtnPressed(_ sender: UIButton) { if isPopoverPresented { dismiss(animated: true) { self.isPopoverPresented = false } return } myWebViewVC.modalPresentationStyle = .popover myWebViewVC.popoverPresentationController?.delegate = self myWebViewVC.popoverPresentationController?.sourceView = sender myWebViewVC.popoverPresentationController?.sourceRect = sender.bounds myWebViewVC.popoverPresentationController?.passthroughViews = [scnView] present(myWebViewVC, animated: true) { self.isPopoverPresented = true } } func popoverPresentationControllerShouldDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) -> Bool { return false } func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) { isPopoverPresented = false } }
这样修改后,就能完全满足你的需求:
- Popover显示期间,SCNView的相机控制手势可以正常响应
- 只有点击铃铛按钮才能关闭Popover,点击外部区域不会触发关闭
内容的提问来源于stack exchange,提问作者grzebyk
相关产品推荐
相关产品推荐

