是否可以在iPhone的UIWebview
中更改JavaScript提醒标题?
答案 0 :(得分:57)
基本上你不能改变标题,但最近我找到了一种显示没有标题的警告对话框的方法。
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", 'data:text/plain,');
document.documentElement.appendChild(iframe);
window.frames[0].window.alert('hello');
iframe.parentNode.removeChild(iframe);
答案 1 :(得分:15)
我为这个问题提出了三个独立的解决方案。生产代码的最佳解决方案是@Martin H描述的解决方案。我对此的唯一补充是展示如何实现它的具体示例。
我的其他解决方案依赖于UIWebView的未记录行为,但不需要对内容/ JS进行任何更改。
解决方案1 :这是一个展示@Martin H提出的技术的具体示例。这可能是最佳解决方案,因为它不依赖于UIWebView
/ {{1}无证行为。
UIAlertView
解决方案2:首先,我要说在生产代码中我绝不会亲自使用以下解决方案。实现此功能的最佳方法是做@Martin H在他的回答中建议的内容,或者可能是@twk建议如果空标题实际上是所需的。如果您无法控制Web内容本身,也许您可以在加载内容后注入@Martin H的代码。
尽管如此,如果我们做出一些假设,这是可以实现的。首先,Javascript @interface TSViewController () <UIWebViewDelegate>
@end
@implementation TSViewController
- (UIWebView*) webView
{
return (UIWebView*) self.view;
}
- (void) loadView
{
UIWebView* wv = [[UIWebView alloc] initWithFrame: CGRectMake(0, 0, 320, 480)];
wv.delegate = self;
wv.scalesPageToFit = YES;
self.view = wv;
}
- (void) viewDidLoad
{
[super viewDidLoad];
[self.webView loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: @"http://www.craigslist.org"]]];
}
- (void) webViewDidFinishLoad: (UIWebView *) webView
{
// inject some js to re-map window.alert()
// ideally just do this in the html/js itself if you have control of that.
NSString* js = @"window.alert = function(message) { window.location = \"http://action/alert?message=\" + message; }";
[webView stringByEvaluatingJavaScriptFromString: js];
// trigger an alert. for demonstration only:
[webView stringByEvaluatingJavaScriptFromString: @"alert('hello, world');" ];
}
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL* url = request.URL;
// look for our custom action to come through:
if ( [url.host isEqualToString: @"action"] && [url.path isEqualToString: @"/alert"] )
{
// parse out the message
NSString* message = [[[[url query] componentsSeparatedByString: @"="] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// show our alert
UIAlertView* av = [[UIAlertView alloc] initWithTitle: @"My Custom Title"
message: message
delegate: nil
cancelButtonTitle: @"OK"
otherButtonTitles: nil];
[av show];
return NO;
}
return YES;
}
方法确实映射到真实的alert()
。 (事实上确实如此!)其次,我们可以提出一些机制来识别来自其他应用程序源UIAlertView
的{{1}}来源alert()
。 (我们可以!)
我的方法是调动UIAlertView
。我知道 - swizzling sucks and has all sorts of drawbacks。如果我能提供帮助,我不会在生产应用程序中徘徊。但对于这个科学项目,我们将调整UIAlertViews
方法。
我发现1)UIAlertView
将构建一个UIAlertView setDelegate:
以显示javascript警报,以及2){UENlertView UIWebView
之前设置UIAlertView
标题已设定。通过使用我自己的方法调动UIAlertView
,我可以完成两件事:1)我可以确定delegate
代表UIAlertView setDelegate:
进行委托(只需检查代表......) 2)我有机会在显示警报视图之前重新设置标题。
您可能会问“为什么不只是调动UIAlertView
方法?”这会很棒,但在我的实验中我发现UIWebView从未调用过UIWebView
。它必须调用其他一些内部方法,我没有进一步调查。
我的解决方案在UIAlertView上实现了一个类别,它添加了几个类方法。基本上,您使用这些方法注册UIWebView,并提供要使用的替换标题。或者,您可以提供一个回调块,在调用时返回标题。
我使用iOS6 UIAlertview -show
类来保存一组UIWebView到标题的映射,其中UIWebView是一个弱键。这样我就不必取消注册我的show
,一切都得到了很好的清理。 因此,此当前实现仅限iOS6。
以下是在基本视图控制器中使用的代码:
NSMapTable
解决方案3 :经过反思,这是一种比我最初在解决方案2中描述的更简单的技术。它仍然取决于未记录的事实,即javascript警报是使用其委托设置为的UIAlertView实现的采购UIWebView。对于这个解决方案,只需子类化UIWebView并为UIAlertView willPresentAlertView:实现自己的委托方法,并在调用它时,将标题重置为您想要的任何内容。
UIWebView
答案 2 :(得分:10)
不能在Javascript警报中执行此操作。
但是如果Javascript是你的,那么你可以改为调用Objective C并调用iOS本机警报,而不是调用警报。
如果Javascript不是您的,那么使用UIWebView您可以注入一些Javascript来覆盖默认行为并将其更改为调用iOS本机警报,例如类似
window.alert = function(message) {
window.location = "myScheme://" + message"
};
然后在UIWebView的shouldStartLoadWithRequest中查找myScheme并解压缩消息
这是从Javascript调用Objective-C的标准方法
答案 3 :(得分:4)
对于它的价值,Phonegap / Cordova提供navigator.notification.alert功能。它允许指定自定义标题。
答案 4 :(得分:1)
只需为您的UIWebView创建一个类,并在其中创建willPresentAlertView(alertView:UIAlertView)函数。之后设置alertView.title = "your fav title"
并完成。
import UIKit
class webviewClass: UIWebView {
func willPresentAlertView(alertView: UIAlertView) {
alertView.title = "my custum title"
}
}
之后,当显示警告或确认并显示时,将显示您的自定义标题。
答案 5 :(得分:0)
关于@twk所写的内容,我只是覆盖了警报功能。适用于ios7。
function alert(words){
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", 'data:text/plain,');
document.documentElement.appendChild(iframe);
window.frames[0].window.alert(words);
iframe.parentNode.removeChild(iframe);
}
答案 6 :(得分:0)
使用cordova-plugin-dialogs。它允许创建原生对话框。
下面的代码将创建本机警报:
navigator.notification.alert(message, alertCallback, [title], [buttonName])