如何在UIWebView渲染完成前阻止Javascript中的alert、confirm、promt弹窗?

6
已经有多个SO问题涉及类似的问题,但没有一个回答了我确切类型的问题。大多数答案都涉及运行JS代码并重载警报方法,如下所示:window.alert = function() {}; 我的问题是,在整个页面渲染完成之前,加载的网页(我无法控制其内容)会打开一个警报。
因此,我不能使用- (void)webViewDidFinishLoad:(UIWebView *)webView委托方法来运行JS代码片段。此外,在- (void)webViewDidStartLoad:(UIWebView *)webView中运行相同的片段对我没有任何好处,因为它在DOM加载之前执行。
类似的问题: 有什么建议吗?

你能把创建警告框的脚本移动到</body>标签的上一行吗? - DrogoNevets
你是在建议我预加载HTML并解析警报代码然后移动它吗?我正在寻找一个更健壮的解决方案。 - ABeanSits
如果你对其他任何事情都没有控制,那么我想我是这样做的,如果你不覆盖警报,我看不出还有什么其他方法可以做到。 - DrogoNevets
2个回答

9

在尝试注入Javascript的建议解决方案后,我回归到了本地平台。

由于UIWebView将所有Javascript警报转换为本地UIAlertViews,因此在本地端阻止它相当简单。查看UIAlertView.h,只有一个公共方法用于显示警报,方便地称为:- (void)show;

这种方法可以很容易地通过子类或类别进行覆盖。由于文档提到了对UIAlertView进行子类化的警告,因此我最终使用了类别。

@interface UIAlertView (Blocker)
@end

#import "UIAlertView+Blocker.h"

@implementation UIAlertView (Blocker)

- (void)show {
   return;
}
@end

在持有 UIWebView 的视图控制器中导入这个类别将阻止所有 UIAlertView 实例以及所有 JS 弹出框。

我认为这种解决方案更加健壮,因为它不依赖于注入 JavaScript、更改 HTML 或使用第三方库。它也与时间无关(JS 弹出框代码可以放在头文件、主体文件或某些第三方库中)。


使用分类覆盖方法是 Apple 强烈反对的做法 - Guillaume Algis

0

看起来结果可能会因渲染引擎而异,有几种方法,我发现这种方式可行:

alert("something");
alert = function(){};
alert("awesome");

http://jsfiddle.net/g5S5M/ 我知道Chrome使用的V8引擎与Firefox或IE使用的不同,所以在制作复杂的网页应用程序时,我们必须开始思考,因为并不是所有浏览器都以相同方式解析JavaScript。

你可能想要关注的一件事是覆盖这个函数的第三方库,比如当你告诉alert为空白,而另一个脚本告诉它不为空白时,要么移除该库,改变执行顺序,要么修改该库。


我可以确认,在整个页面加载完成后显示警告的网页上(已调用webViewDidFinishLoad:),此解决方法有效。但我现在遇到的问题是,弹出窗口在所有内容渲染之前就打开了。 您是在建议我注入某种JS库来处理这个问题吗? - ABeanSits
你可以将它包装在一个isReady函数中。http://learn.jquery.com/using-jquery-core/document-ready/ - Theodor Solbjørg
我最终使用了本地解决方案来解决这个问题。这种方法感觉更加健壮,并且更符合我的舒适区域。 - ABeanSits

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接