武之新
[iPhone]UIWebViewでNew Windowをなんとか検知する

先日(どころか実際には昨年から)ハマってるUIWebViewですが、懸案課題のNew Windowの検知が次のような姑息なアイデアでなんとかなりました!

やり方は次の2つの組み合わせ。

  1. UIWebViewの webView:willClickElement: をoverrideして、elementからtarget属性を探す。(Aタグ用)
  2. UIWebViewの stringByEvaluatingJavaScriptFromString: でJavascriptの”window.open”を書き換えてしまい、window.openされたら特殊なURLに飛ぶようにして、webView:shouldStartLoadWithRequest:navigationType: で検知する。(Javascript用)

(1)は簡単で、次のような感じ。

@implementation UIWebView(hack)

- (void)webView:(UIWebView *)sender willClickElement:(id)element {
    BOOL is_new_window = NO;
    NSString* nodeName = [element nodeName];
    NSString* hrefURL = [element hrefURL];
    NSString* textContent = [element textContent];
    id attributes = [element attributes];
    int length = [attributes length];
    for(int i = 0; i < length; i++ ) {
        id item = [attributes item:i];
        NSString* name = [item name];
        NSString* value = [item value];
        
        if (NSOrderedSame == [name compare:@”target” options:NSCaseInsensitiveSearch]){
            is_new_window = YES;
            break;
        }
    }
    
    if (is_new_window){
        NSLog(@”clicked!!”);
    }
}

@end

これは http://son-son.sakura.ne.jp/?p=752 を参考にさせてもらいました。

(2)はなかなか面倒で、次の2ステップが必要。
まず、webViewDidFinishLoad: でwindow.openを書き換える。書き換え方は

[webView stringByEvaluatingJavaScriptFromString:
 @”window.open = function(url, window_name, options){ 
    window_name = window_name == ” ? ‘_blank’ : window_name;
    location.href = ‘wopen://’ + (window_name == null ? ‘_blank’ : window_name) + ‘/’ + url; 
    };”];

こんな感じ。あとでURLからwindow.openが呼ばれたことと、遷移したいURLがわからなければならないので、schemeを独自のものに書き換えてしまうのがよいと思う。

続いて、webView:shouldStartLoadWithRequest:navigationType: で検知する部分。

- (BOOL)webView:(UIWebView *)webView 
    shouldStartLoadWithRequest:(NSURLRequest *)request 
    navigationType:(UIWebViewNavigationType)navigationType
{
    NSURL *url = [request URL];    
    if ([[url scheme] isEqualToString:@”wopen”]){
        NSString *host = [url host];
        if (host != nil && [host isEqualToString:@”_blank”]){
            NSLog(@”new window!”);
        }
        return NO;
    }

    return YES;
}    

URLのscheme部分をみてwindow.openなのかどうかを見極め、遷移先を[URL path]で取って、あとは自分でどうにかする、という感じです。

自分もまだ基礎実験までしかやってないので、すごく見切り発車的エントリです w
このあとアプリに実装してみようと思います。