这个 Bug 是我由同事发现并确认的,一开始我还不相信 Apple 会犯这么低级的错误。截止到目前,所有版本的 iOS7(包括最新的 7.0.2),无论是运行在 iPhone、iPad 上,还是 iPod touch 都有问题。简而言之,这个 Bug 是「某种情况下,Safari 中的 alert、confirm 和 prompt 方法都坏掉。而且重启 Safari 之前,即使刷新或新建 Tab,这个 Bug 始终存在」。至于是什么情况下,会坏成什么样,请继续往下看。
经过分析,以下代码会触发 iOS7 自带 Safari 的这个 Bug:
var iframe = document.createElement("iframe");
iframe.src = "xxx:yyy";
document.body.insertBefore(iframe, document.body.childNodes[0]);
confirm('?');
也就是说,iOS7 中,在页面插入 iframe 时使用了 Safari 不认识的协议;紧接着调用 window.confirm 方法,就会触发这个 Bug。
上面的代码,会几乎同时弹出两个系统浮层:一个是「无法打开页面」提示,一个是 confirm 对话框。正常情况下,confirm 会停止执行后续代码,等待用户选择 Cancel/OK,并返回用户选择的布尔值:
(普通的 confirm。链接)
但在触发了 Bug 的代码中,confirm 会直接返回 false,并继续执行后续代码。虽然也显示对话框,但无论选哪个选项都一样----代码早就执行过了:
(坏掉的 confirm。链接)
更为严重的是:只要激活了这个 Bug,即使新建 Tab 访问其它正常页面,confirm、alert 或 prompt 仍然不停止执行代码,仍然得不到 confirm 和 prompt 的正确返回值(它俩返回值始终是 false 和 null)。
双击 Home 键杀死 Safari,重新打开 Safari 访问正常页面,confirm 等方法才会正常。
我把这个 Bug 汇报给了 Apple,到目前为止没有收到任何回复。目前我们能做的不外乎两点:1)避免使用「触发条件」这一小节提到的代码;2)由于这个 Bug 影响的是整个 Safari,所以尽量不要使用原生 alert、confirm 和 prompt,自己实现具有这些功能的浮层。
update @ 2013.10.24,在更新到 iOS 7.0.3(11B511) 的 iPhone 4s 上测试,本文描述的问题仍未修复。
update @ 2013.11.15,在更新到 iOS 7.0.4(11B554a) 的 iPhone 4s 上测试,本文描述的问题仍未修复。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8