先日(どころか実際には昨年から)ハマってるUIWebViewですが、懸案課題のNew Windowの検知が次のような姑息なアイデアでなんとかなりました!
やり方は次の2つの組み合わせ。
- UIWebViewの webView:willClickElement: をoverrideして、elementからtarget属性を探す。(Aタグ用)
- 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
このあとアプリに実装してみようと思います。