WKWebView中input type="tel"软键盘不弹出,因iOS要求用户手势同步触发focus();需禁用mediaTypesRequiringUserActionForPlayback并开启allowsInlineMediaPlayback;JSBridge传参须encodeURIComponent编码;资源加载应避免file://协议,改用HTTPS或loadHTMLString+baseURL。

WKWebView 中无法自动触发 HTML5 input type="tel" 软键盘
iOS 原生 App 里用 WKWebView 加载含验证码输入框的 H5 页面时,常出现点击无反应、软键盘不弹出的问题。这不是验证码组件本身有 bug,而是 iOS 对 input 元素的聚焦策略更严格:必须满足「用户真实手势触发」+「非异步延迟调用」两个条件,focus() 才会被允许。
- 常见错误写法:
setTimeout(() => input.focus(), 100)—— 异步延迟导致被 iOS 拦截 - 正确做法:在
touchend或click事件回调内**同步**调用input.focus() - 若 H5 由你控制,建议在验证码按钮的
onclick里直接调用document.getElementById('codeInput').focus(),不要包 Promise 或防抖 - 若 H5 不可控(如第三方页面),可在
WKWebView的userContentController注入 JS,在按钮 DOM 出现后监听其click,再同步聚焦输入框
WKWebView 需启用 allowsInlineMediaPlayback 和 mediaTypesRequiringUserActionForPlayback
部分 HTML5 验证码组件(尤其是带语音播报功能的)会依赖 标签播放提示音。iOS 默认禁止自动播放媒体,即使只是短音频,也会静音或报错 NotAllowedError: The request is not allowed by the user agent or the platform in the current context。
- 原生侧必须设置:
wkWebView.configuration.mediaTypesRequiringUserActionForPlayback = [] - 同时开启内联播放:
wkWebView.allowsInlineMediaPlayback = true - 注意:仅设
allowsInlineMediaPlayback不够,必须配合清空mediaTypesRequiringUserActionForPlayback - 若仍不响,检查 H5 是否用了
play().catch(e => console.log(e))—— 错误对象里e.name === 'NotAllowedError'就是这个原因
JSBridge 传参时中文乱码或数字被截断
很多验证码组件通过 JSBridge 向原生发请求(如「获取短信」),参数含手机号或模板 ID。iOS 原生端若用 NSString *param = [message body] 直接取值,遇到 URL 编码或特殊字符会解析失败,表现为手机号末尾缺位、验证码倒序、或整个参数为空。
- H5 发送前必须
encodeURIComponent()编码所有参数字段,尤其phone和templateId - 原生侧收到后需用
CFURLCreateStringByReplacingPercentEscapesUsingEncoding或stringByRemovingPercentEncodingInURL解码 - 避免用
NSJSONSerialization直接解析未 decode 的字符串 —— 容易因 %2B 变成 + 导致 JSON 解析失败 - 调试技巧:在原生
userContentController:didReceiveMessage:里先打 log 看原始body字符串,确认是否已编码
WKWebView 加载 H5 验证码页白屏或资源 404
本地调试时正常,但打包上架后验证码组件加载失败,控制台报 Failed to load resource: The requested URL was not found on this server,实际是 WKWebView 对 file:// 协议的资源加载限制变严了 —— iOS 15.4+ 默认禁用跨域请求,且不允许从本地 HTML 加载远程 JS/CSS。
立即学习“前端免费学习笔记(深入)”;
- 不要把验证码组件的 JS 文件放在
bundle里用file://引入;统一走 HTTPS 加载,哪怕只是测试域名 - 若必须离线使用,改用
loadHTMLString:baseURL:,并把baseURL设为[[NSBundle mainBundle] bundleURL] - 检查 H5 是否用了
fetch('/api/send')这类相对路径 —— WKWebView 不会自动补全 host,必须写完整 URL,或由原生注入 base API 地址 - 真机调试时打开 Web Inspector(Safari → Develop → iPhone),看 Network 面板里具体哪个资源 failed,比猜快得多
真正卡住的往往不是「怎么调」,而是 iOS 在不同版本里对焦点、媒体、协议、编码的隐式限制层层叠加。每次升级系统或 SDK 后,都得重新验证这几个点。










