如何在iOS应用中禁用3D Touch,自定义处理WebView链接?
我之前也踩过这个坑!3D Touch的链接预览功能确实会绕开WebView的代理方法,直接跳转到Safari,挺烦人的。其实不用一刀切禁用整个App的3D Touch,有几种更精准的处理方式,当然如果你确实需要全局禁用也可以,下面给你详细说:
方法一:仅针对WebView禁用链接的3D Touch预览(最优解)
这种方式不会影响App其他地方的3D Touch功能,只针对WebView里的链接生效,推荐优先用。
方式1:注入JavaScript禁用链接预览
WebView加载完成后,注入一段JS代码,禁用所有链接的webkitTouchCallout(这就是触发3D Touch预览的核心属性):
// Swift 代码示例 webView.evaluateJavaScript("document.addEventListener('DOMContentLoaded', function() { const links = document.getElementsByTagName('a'); for(let i = 0; i < links.length; i++) { links[i].style.webkitTouchCallout = 'none'; } });", completionHandler: nil)
// Objective-C 代码示例 [self.webView evaluateJavaScript:@"document.addEventListener('DOMContentLoaded', function() { var links = document.getElementsByTagName('a'); for(var i = 0; i < links.length; i++) { links[i].style.webkitTouchCallout = 'none'; } });" completionHandler:nil];
这样用户不管是长按还是3D Touch链接,都不会弹出系统的预览框,自然也就不会跳Safari了,你的代理方法依然能正常处理点击事件,而且还能保留WebView的长按选文本等功能。
方式2:拦截WebView的手势识别器
WebView自带的手势识别器里,有一个负责3D Touch预览的长按手势,你可以直接禁用它:
// Swift 代码示例 for gesture in webView.gestureRecognizers ?? [] { if gesture is UILongPressGestureRecognizer { gesture.isEnabled = false } }
⚠️ 注意:这种方式会同时禁用WebView里的长按复制、选文本等功能,如果你的WebView需要这些交互,就别用这个方法。
方法二:全局禁用App的3D Touch功能
如果你确实想要整个App都关闭3D Touch,直接修改Info.plist就行:
- 打开项目的Info.plist文件
- 添加字段
UIApplicationSupportsIndirectInputEvents,类型设为Boolean,值设为NO
这个设置会禁用所有系统级的3D Touch功能,包括App图标快捷操作、页面预览等,所以一定要谨慎考虑后再用。
进阶玩法:接管3D Touch预览(不禁用,自定义处理)
如果你不想禁用3D Touch,而是想让预览也在App内处理,可以实现UIViewControllerPreviewingDelegate协议,接管WebView中链接的预览逻辑。比如用户3D Touch链接时,弹出你自己的预览控制器,而不是跳Safari。不过这个实现稍微复杂一点,需要你解析WebView中的点击链接,再创建对应的预览内容,适合有定制需求的场景。
总结一下,优先推荐方法一的JavaScript注入方式,既能解决问题,又不会影响其他功能的正常使用。
内容的提问来源于stack exchange,提问作者ozd

