JavaScript alert をオーバライドして対処

WebUIDelegate Protocol Reference によると、

- webView:runJavaScriptAlertPanelWithMessage:
- webView:runJavaScriptConfirmPanelWithMessage:
- webView:runJavaScriptTextInputPanelWithPrompt:defaultText:

これらは、Deprecated in Mac OS X v10.4.11 となっている。

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/WebKit/Protocols/WebUIDelegate_Protocol/Reference/Reference.html

では、他の方法を考えると、alert はどうにかなる。しかし、confirm prompt は、呼び出し元の JavaScript に、
BOOL か、文字列を返さないといけない。
上の delegate を使わずに confirm や prompt はどうしたらいいのか?

alert は、オーバーライドして、任意の プロトコル(http の代わりに定義するプロトコル)で、
JavaScript の document.location を書き変えて、UIWebView 側で捕捉して AlertView を実行すればよい。

   -(void)webViewDidFinishLoad: ( UIWebView* ) webView の中で、以下のように、
alert をオーバライド実行する。


[self.webViewstringByEvaluatingJavaScriptFromString:@"(function(){ "
         "       window.alert = function() { "
         "          document.location=\"
bridge://alert-\"+encodeURI(arguments[0]); "
         "       };                          "
         "    }                              "
         " )();                              "

];


  shouldStartLoadWithRequest で、@"bridge://alert-" を捕捉

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{

    if ([ [[request URL] absoluteString] rangeOfString:@"bridge://alert-"].location != NSNotFound){

        // URL から、alert メッセージを切りだす。
        NSString *str = [[[request URL] absoluteString] substringFromIndex:15];
        
        // alert の文字列を URLデコード
        NSString *decodedString = (NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)str, CFSTR(""), kCFStringEncodingUTF8);

        // 任意に定義するメソッドを call
        [ self alertIntercept:decodedString ];

        // このプロトコルは、以降、UIWebView の処理をしない。
        return NO;
    }

shouldStartLoadWithRequest から呼ばれるメソッドで、AlertView を表示する


-( void )alertIntercept:(NSString*)message
{
    UIAlertView* dialog = [[UIAlertViewalloc] initWithTitle:nilmessage:message  delegate:nil  cancelButtonTitle:@"OK"  otherButtonTitles:nil ];
    [dialog show];
    [dialog autorelease];
}

alert メッセージは、URLエンコードする必要がある。