UIWebViewではWEBページ読み込み中はloadingプロパティで判別できるが、ページ読み込み完了を検知する方法が標準のdelegateなどにはなかったので(私が調べた感じでは)検知する方法を調べた。
シンプルなWEBページだったらwebViewDidFinishLoadメソッドがコールバックされたタイミング=ページ読み込み完了でよいと思うが、Webページ側でwindowのloadメソッドや$(document).readyを利用してコンテンツの遅延読み込みを行っていると、
何度もwebViewDidFinishLoadメソッドがコールバックされてどのタイミングでWEBページのロードが完了しているかがわからなかった。今回の投稿はそれを検知する方法である。
調べた経緯:
・UIWebViewの表示内容をJQueryのDOM操作(stringByEvaluatingJavaScriptFromStringメソッドを利用)で変更したかったのだが、そのDOM操作がページ読み込み完了後じゃないと適用されなかったため。
解決方法
-
webViewDidFinishLoadメソッドがコールバックされたタイミングで、WEBページ側(JavaScript)のwindowのloadイベントに以下の処理を登録。
- pageloadedスキーマ(カスタムスキーマ)に飛ばす
- page_statusに読み込み完了(page_status = 'loaded')をセット
-
pageloadedスキーマがWEBページから発行されたタイミングをアプリ側でフック(webView:shouldStartLoadWithRequestnavigationType:メソッド)。
このタイミングがページ読み込み完了のタイミング。
参考:http://stackoverflow.com/questions/10996028/uiwebview-when-did-a-page-really-finish-loading
→jasonjwwilliamsさんの解答を参考にさせていただいた。最後の"Here's a simplified version of・・・"のコードはコメントにもあるようにちょっと不完全な気がしたので利用していない。
window.addEventListener("load", function(){
window.location.href = 'pageloaded:' + window.location.href;
window.page_status = 'loaded'
}, false);
/*
//JQuery利用の場合
$(function(){
window.location.href = 'pageloaded:' + window.location.href;
window.page_status = 'loaded'
});
*/
class ViewController: UIViewController,UIWebViewDelegate {
@IBOutlet weak var webView: UIWebView!
var js_func_String:String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//bundleのjsファイル読み込み
let jsPath = NSBundle.mainBundle().pathForResource("addPageloadedEvent", ofType: "js")!
js_func_String = try? String(contentsOfFile:jsPath, encoding: NSUTF8StringEncoding)
let req = NSURLRequest(URL: NSURL(string: "http://qiita.com")!)
webView.loadRequest(req)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func javaScriptPageLoaded() -> Bool {
if let page_status = webView.stringByEvaluatingJavaScriptFromString("window.page_status") {
print("page_status:" + page_status)
return page_status == "loaded"
}
print("page_status:nil")
return false
}
// MARK: UIWebViewDelegate
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if (request.URL?.scheme == "pageloaded") {
//////////////////////////////////////////////
// ここでWEBページ読み込み完了
//////////////////////////////////////////////
print("⭐️page load conmplete!")
return false
}
return true
}
func webViewDidStartLoad(webView: UIWebView) {
let str = webView.request?.URL?.absoluteString ?? ""
print(__FUNCTION__ + " URL:" + str)
}
func webViewDidFinishLoad(webView: UIWebView) {
let str = webView.request?.URL?.absoluteString ?? ""
print(__FUNCTION__ + " URL:" + str)
if (!self.javaScriptPageLoaded()) {
webView.stringByEvaluatingJavaScriptFromString(js_func_String!)
}
}
func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
print(error)
}
}