WKWebview键盘输入偶发死锁求助(iOS17情况加剧)
WKWebView键盘输入偶发死锁(iOS17恶化)排查与解决方案
调用栈分析
从提供的调用栈来看,死锁核心出现在键盘自动纠错逻辑的跨线程同步等待环节:
- 主线程卡在
-[UIKeyboardTaskQueue lockWhenReadyForMainThread]等待条件锁释放,而该锁的持有或任务队列调度出现阻塞。 - 整个触发链路是:
UIWKTextInteractionAssistant发起自动纠错请求,通过IPC向WebKit进程获取WebAutocorrectionData,回调回到主线程时触发键盘任务队列的锁等待,最终导致死锁。 - iOS17后问题恶化,大概率是苹果调整了该版本中键盘自动纠错的线程调度或IPC交互逻辑,加剧了线程竞争冲突。
已尝试方案失效原因
仅设置网页input的autocorrect=off,只能禁用网页层面的自动纠错,但WKWebView内置的UIWKTextInteractionAssistant仍会触发系统级文本替换、拼写检查等逻辑,无法彻底阻断死锁的触发链路。
可行解决方案
1. 配置层面彻底禁用WebKit文本辅助功能
直接在WKWebView配置中关闭拼写检查、自动纠错及文本替换,从根源切断触发逻辑:
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; // 禁用拼写检查 if (@available(iOS 10.0, *)) { config.defaultWebPreferences.spellCheckingEnabled = NO; } // 禁用自动纠错与文本替换 config.defaultWebPreferences.autocorrectionEnabled = NO; config.defaultWebPreferences.automaticTextReplacementEnabled = NO; // 初始化WebView WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
该方案比网页端设置更彻底,直接从WebKit内核层面禁用相关功能,无审核风险。
2. Runtime拦截自动纠错弹窗触发逻辑
通过方法交换拦截UIWKTextInteractionAssistant的纠错弹窗触发方法,阻断死锁链路:
#import <objc/runtime.h> @implementation UIWKTextInteractionAssistant (DeadLockFix) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ SEL originalSel = @selector(showReplacementsForText:withOptions:rects:); SEL swizzledSel = @selector(fix_showReplacementsForText:withOptions:rects:); Method originalMethod = class_getInstanceMethod(self, originalSel); Method swizzledMethod = class_getInstanceMethod(self, swizzledSel); BOOL didAdd = class_addMethod(self, originalSel, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (didAdd) { class_replaceMethod(self, swizzledSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } }); } - (void)fix_showReplacementsForText:(NSString *)text withOptions:(NSDictionary *)options rects:(NSArray *)rects { // 空实现,阻断纠错弹窗及后续逻辑 } @end
注意:使用Runtime方法交换需注意苹果审核风险,建议通过开关控制仅在死锁场景启用。
3. 等待官方修复+提交Bug反馈
- 持续关注iOS17后续小版本更新,苹果可能在补丁中修复该死锁问题;
- 整理复现步骤、设备信息、完整调用栈,通过苹果Feedback Assistant提交Bug报告,推动官方修复。
4. 极端场景备选:异步化键盘任务(风险较高)
如果必须保留自动纠错功能,可尝试将键盘任务队列的同步执行改为异步,但可能破坏键盘内部逻辑,仅作为最后备选:
@implementation UIKeyboardTaskQueue (DeadLockFix) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Method originalMethod = class_getInstanceMethod(self, @selector(performSingleTask:)); Method swizzledMethod = class_getInstanceMethod(self, @selector(fix_performSingleTask:)); method_exchangeImplementations(originalMethod, swizzledMethod); }); } - (void)fix_performSingleTask:(void (^)(void))task { dispatch_async(dispatch_get_main_queue(), task); } @end
总结
优先尝试方案1(配置层面禁用文本辅助功能),若无效再考虑方案2的Runtime拦截。方案4风险较高,仅在极端场景下使用。同时建议提交官方Bug反馈,等待系统层面的彻底修复。
内容的提问来源于stack exchange,提问作者Luhui
相关产品推荐
相关产品推荐

