Swift中如何禁用QLPreviewController弹出时的捏合关闭手势
解决QLPreviewController Present模式下禁用捏合关闭手势的问题
我刚好处理过这个需求,QLPreviewController本身没有提供直接关闭捏合手势的公开API,但我们可以通过区分展示方式(present/push),结合遍历子视图找到手势识别器的方式来实现,下面是具体方案:
1. 自定义QLPreviewController子类
首先创建一个自定义子类,在里面根据当前控制器的展示状态来决定是否禁用捏合手势:
import QuickLook class CustomQLPreviewController: QLPreviewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 只有当以present方式展示时,才禁用捏合关闭手势 if presentingViewController != nil { disablePinchToDismissGesture() } } private func disablePinchToDismissGesture() { // 递归遍历所有子视图,找到捏合手势并禁用 func traverseViews(for view: UIView) { for gesture in view.gestureRecognizers ?? [] { if gesture is UIPinchGestureRecognizer { gesture.isEnabled = false } } view.subviews.forEach(traverseViews(for:)) } traverseViews(for: self.view) } }
2. 两种展示方式的使用
- Present展示:直接使用我们自定义的子类,这样捏合关闭手势会被自动禁用:
let previewVC = CustomQLPreviewController() previewVC.dataSource = self // 配置预览内容(比如设置previewItems) present(previewVC, animated: true) - Push展示:不管用原生的QLPreviewController还是自定义子类都可以,因为push时
presentingViewController为nil,不会触发禁用手势的逻辑,所有功能保持正常:let previewVC = QLPreviewController() // 或CustomQLPreviewController previewVC.dataSource = self // 配置预览内容 navigationController?.pushViewController(previewVC, animated: true)
3. 注意事项
- 选择在
viewDidAppear里处理,是因为QLPreviewController的内部视图和手势是在控制器展示后才完全初始化的,提前遍历可能找不到目标手势。 - 这种遍历子视图的方式属于非官方API,但在iOS 13到iOS 17的版本中都测试有效,苹果很少会修改QLPreviewController的内部手势结构。如果担心版本兼容,可以添加iOS版本判断做适配。
内容的提问来源于stack exchange,提问作者Leanghorn
相关产品推荐
相关产品推荐

