iOS Safari中contenteditable元素点击误拼写词弹出建议菜单问题
解决方案
一、原生Swift/Objective-C实现方案
核心思路是拦截WKWebView的上下文菜单生成过程,过滤掉拼写修正相关的菜单项,同时保留输入时的拼写建议功能。
Swift 版本
通过自定义WKUIDelegate的菜单配置方法,过滤不需要的拼写修正选项:
extension YourViewController: WKUIDelegate { func webView(_ webView: WKWebView, contextMenuConfigurationForElement elementInfo: WKContextMenuElementInfo, completionHandler: @escaping (UIContextMenuConfiguration?) -> Void) { // 调用默认代理获取原始菜单配置 webView.defaultUIDelegate?.webView?(webView, contextMenuConfigurationForElement: elementInfo, completionHandler: { originalConfig in guard let config = originalConfig else { completionHandler(nil) return } // 过滤拼写修正类菜单项(通过标识符关键词匹配) let filteredMenuItems = config.menuItems?.filter { item in guard let identifier = item.identifier as? String else { return true } return !identifier.contains("SpellChecker") && !identifier.contains("Correction") } // 构造新的上下文菜单配置 let newConfig = UIContextMenuConfiguration( identifier: config.identifier, previewProvider: config.previewProvider ) { _ in UIMenu( title: "", image: nil, identifier: nil, options: config.menu?.options ?? [], children: filteredMenuItems ?? [] ) } completionHandler(newConfig) }) } }
使用时需将WKWebView的uiDelegate设置为当前ViewController。
Objective-C 版本
@interface YourViewController () <WKUIDelegate> @end @implementation YourViewController - (void)webView:(WKWebView *)webView contextMenuConfigurationForElement:(WKContextMenuElementInfo *)elementInfo completionHandler:(void (^)(UIContextMenuConfiguration * _Nullable))completionHandler { [webView.defaultUIDelegate webView:webView contextMenuConfigurationForElement:elementInfo completionHandler:^(UIContextMenuConfiguration * _Nullable originalConfig) { if (!originalConfig) { completionHandler(nil); return; } // 过滤拼写修正相关菜单项 NSMutableArray *filteredItems = [NSMutableArray array]; for (UIMenuItem *item in originalConfig.menuItems) { NSString *identifier = item.identifier; if (![identifier containsString:@"SpellChecker"] && ![identifier containsString:@"Correction"]) { [filteredItems addObject:item]; } } // 创建新的菜单配置 UIContextMenuConfiguration *newConfig = [UIContextMenuConfiguration configurationWithIdentifier:originalConfig.identifier previewProvider:originalConfig.previewProvider actionProvider:^UIMenu * _Nullable(NSArray<UIMenuElement *> * _Nonnull suggestedActions) { return [UIMenu menuWithTitle:@"" image:nil identifier:nil options:originalConfig.menu.options children:filteredItems]; }]; completionHandler(newConfig); }]; } @end
补充优化方案:配合JS拦截上下文菜单触发(仅针对目标元素)
可以注入一段JS代码,监听目标div的右键/长按事件,在特定条件下阻止默认菜单弹出,配合原生过滤进一步确保效果:
const editableDiv = document.querySelector('div[contenteditable="true"][spellcheck="false"]'); editableDiv.addEventListener('contextmenu', (e) => { // 仅针对拼写检查关闭的可编辑元素阻止默认菜单 if (!editableDiv.spellcheck) { e.preventDefault(); } });
通过WKWebView的evaluateJavaScript:方法将上述代码注入页面。
二、WebKit源码中控制该菜单的关键位置
WebKit中拼写检查上下文菜单的核心逻辑分布在以下文件:
- WebKit/UIProcess/API/Cocoa/WKWebView.mm:处理WKWebView上下文菜单的创建与代理转发逻辑
- WebKit/UIProcess/SpellChecker.cpp:生成拼写修正建议菜单项的核心实现
- WebKit/UIProcess/WebPageProxy.cpp:负责页面级别的上下文菜单请求传递
- WebCore/editing/SpellChecker.cpp:WebCore层的拼写检查核心,处理文本验证与建议生成
其中SpellChecker类的createContextMenuItems方法是生成拼写修正菜单项的关键入口,该方法会将建议项传递到UIProcess层,最终在WKWebView的上下文菜单中展示。
内容的提问来源于stack exchange,提问作者Calebmer
相关产品推荐
相关产品推荐

