为何UITransitionView/UIPopoverView/_UIPopoverStandartChromeView莫名触发按钮?
这种问题我之前在项目里也遇到过几次,结合iOS的视图层级和事件传递机制,可能的原因大概有这几个方向:
事件传递的意外穿透
iOS的事件响应链是从最上层视图往下传递的,正常情况下UITransitionView、UIPopoverView这类系统过渡视图的userInteractionEnabled应该是false,不会接收触摸事件。但如果它们被意外设置为true,或者在移除/隐藏时没有正确取消事件监听,就可能导致触摸事件被它们接收后,错误地透传到下层的按钮上。
排查建议:问题出现时,用Xcode的View Debugger查看这些视图的userInteractionEnabled属性;或者在按钮的点击回调里打印sender和触摸事件的view信息,确认事件的来源是否异常。Popover/过渡动画的异常残留
当使用UIPopoverPresentationController或者自定义过渡动画时,如果动画中途被打断(比如快速切换页面、内存警告导致控制器被释放),这些系统过渡视图可能没有被正确从视图层级中移除,而是处于隐藏状态留在屏幕上。后续触摸落在它们的区域时,就可能触发下层按钮的事件。
排查建议:在popover dismiss、过渡动画完成的回调中,检查当前窗口的视图层级,看是否存在残留的_UIPopoverStandartChromeView这类视图,如果有,手动调用removeFromSuperview清理掉。第三方库或自定义代码的干扰
有些第三方UI库(比如弹窗、路由框架)可能会修改系统视图层级,或者自定义过渡逻辑时不小心保留了系统过渡视图。另外,如果你的代码里有直接操作UIWindow根视图、手动批量添加/移除视图的逻辑,也可能出现这类遗漏。
排查建议:回溯近期引入的第三方库,逐一排查;检查涉及视图层级修改的代码段,确保所有临时添加的过渡视图都有对应的移除逻辑。特定iOS版本的系统bug
部分iOS版本存在系统过渡视图回收的bug,比如在popover快速多次弹出/关闭、屏幕旋转的场景下,这些视图没有被正确销毁。
排查建议:在不同iOS版本的设备上测试问题是否复现,如果只出现在特定版本,可以针对性做兼容处理——比如在过渡完成后,主动遍历视图层级,清理残留的系统过渡视图。
内容的提问来源于stack exchange,提问作者János

