harukazepc’s blog

インターネッツとAndroidなどが大好きです。あとは日々のことなど。

Ti.UI.WebView で、遷移先(遷移しようとしている)URLを知りたい 〜 'beforeload' イベントで url が反映されない件 #titaniumjp #titanium

WebView内での遷移(ページのロードとか、リンククリックとか)のタイミングにあわせて、処理を行いたい場合があるかと思います。

その際に、WebViewでは以下の様なイベントが用意されています。
Appcelerator Developer Center - API for Titanium.UI.WebView

  • beforeload : WebView内でページの読み込みを開始した時
  • load : WebView内でページの読み込みが完了した時
  • error : ページの読み込み中に問題が発生した時

WebViewを利用したアプリケーションの場合によくあるのが、

特定のドメイン(URL)じゃないページへ遷移する場合は、通常のブラウザアプリ(Safari等)で開く

という要件です。


その際、beforeload イベントで遷移先のURLが取得できるように(ドキュメント上は?)なっています。

var webview = Titanium.UI.createWebView({url:'http://www.google.com/'});
webview.addEventListener('beforeload',function(e){
    alert('start moving to'+e.url);
});

ですが、iOSアプリの場合、この e.url が更新されないようです。(※Androidは大丈夫)


このバグ?自体は、下記のように今後修正されるようですが、
https://github.com/appcelerator/titanium_mobile/pull/538
https://github.com/appcelerator/titanium_mobile/commit/63c63147367ce14f242abe0363ce74c729b6c41d#diff-0

これだと iframe 等の読み込みでも発行されてしまうようなので、ものによるとは思いますが、こっちの方が良い気がしたり。*1

--- TiUIWebView.m.orig	2012-03-07 17:18:10.000000000 +0900
+++ TiUIWebView.m	2012-03-09 15:15:03.000000000 +0900
@@ -638,6 +638,16 @@
 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
 {
 	NSURL * newUrl = [request URL];
+
+        if ([self.proxy _hasListeners:@"beforeload"])
+        {
+                if (navigationType != UIWebViewNavigationTypeOther)
+                {
+                        NSDictionary *event = newUrl == nil ? nil : [NSDictionary dictionaryWithObject:[newUrl absoluteString] forKey:@"url"];
+                        [self.proxy fireEvent:@"beforeload" withObject:event];
+                }
+        }
+
 	NSString * scheme = [[newUrl scheme] lowercaseString];
 	if ([scheme hasPrefix:@"http"] || [scheme hasPrefix:@"app"] || [scheme hasPrefix:@"file"] || [scheme hasPrefix:@"ftp"])
 	{
@@ -668,11 +678,6 @@
 
 - (void)webViewDidStartLoad:(UIWebView *)webView
 {
-	if ([self.proxy _hasListeners:@"beforeload"])
-	{
-		NSDictionary *event = url == nil ? nil : [NSDictionary dictionaryWithObject:[url absoluteString] forKey:@"url"];
-		[self.proxy fireEvent:@"beforeload" withObject:event];
-	}
 }
 
 - (void)webViewDidFinishLoad:(UIWebView *)webView
@@ -746,4 +751,4 @@
 
 @end

UIWebViewNavigationTypeとして定義されているもののうち、UIWebViewNavigationTypeOther の場合はbeforeloadを発行しない、としています。

自身のTitanium Mobile SDKの TiUIWebView.m に対して、上記のような修正を加えることで反映されます。
(/Library/Application Support/Titanium/mobilesdk/osx/1.7.5/iphone/Classes/TiUIWebView.m 、とか)

*1:というか、修正が反映されたバージョンだと、'beforeload'の発行が、ユーザによる遷移なのか、それともiframe等なのか、判別できるのかなぁ。。。

© harukazepc️