2015-09-18 40 views
11

WKWebViewのスクリーンショットを撮りたいと思います。 Webビューの読み込みが終了した直後にメソッドdrawViewHierarchyInRect(画面更新をtrueに設定)を呼び出します。この目的のために、Webビューのloadingプロパティを観察します。しかし、私が気づいたのは、Webビューでロードが完了したことが通知されたときに、実際に画面に表示されないことに気がつきました。そのため、スクリーンショットは常に白だけです。ロード後0.5秒後にスクリーンショットを撮ると(明らかに長すぎる)、スクリーンショットに希望の結果が表示されます。私の問題は、Webビューが実際に画面に表示されているかどうかわからないため、遅延を0.05に設定する可能性がありますが、毎回動作することを100%保証することはできません。したがって、私の質問は次のようなものです。Webビューが実際に表示されたときにスクリーンショットの準備ができたら通知を受けるにはどうすればいいですか?ビューが実際に表示されるときのWKWebView通知

ありがとうございます!ところで

:私はXcodeの7私はちょうどこの上で働いてきたとして(公式リリース)

答えて

4

でスウィフト2.0とiOS 9を使用しています、私が試したものを知っていると私はそれを考え出した方法。私は、「ステータス」の名前空間上の

let webViewUserScript = WKUserScript(
     source: "window.onload = function() { webkit.messageHandlers.status.postMessage(\(wkwebView.hashValue)) }", 
     injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, 
     forMainFrameOnly: true 
    ) 

WKUserScript

、まず、物事のカップルを試してみました。これは理論的にはすべてのコンテンツをロードするのを待ち、その後、私はすべてが準備ができているだろうと思った

wkwebView.configuration.userContentController.addScriptMessageHandler(self, name: "status") 

経由で登録したときWKScriptMessageHandler

func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage){ } 

を呼び出します。ときどき働いたが、必ずしもそうではなかった。

あなたは、私もWKNavigationDelegateを追加し、再び

func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) { } 

を使用してみてきたように、これは動作しませんでした。また、動作しませんでした

​​

内スクリーンショットをしようとし、その後estimatedProgress値

wkwebView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil) 

ためにオブザーバーを追加します。

しかし、WebViewのコンテンツサイズを定期的に確認するのは何ですか。私はこれをWKUserScriptによって呼び出されるuserContentController関数内で行いましたが、didFinishNavigation関数内でこれを行うこともできますし、再度呼び出す関数を変更することもできます。ここでは、コード:

let _contentSize = webview.scrollView.contentSize; 

if (_contentSize.height == 0){   
    dispatch_after(createDispatchTime(0.01), dispatch_get_main_queue()) { 
       self.userContentController(userContentController, didReceiveScriptMessage: message) 
    } 
    return 
} 

これは本質的にcontentSizeのheightプロパティにチェックし、それがゼロかどうプロパティが設定されるまで、それは再びごとに0.01秒のメソッドを呼び出します。スクリーンショットの作成に使用した関数は次のとおりです。

var view : UIView! 

if self.useSnapShot { 
    // Use the snapshot function 
    view = webView.snapshotViewAfterScreenUpdates(true) 

} else { 
    // Draw the view as UIImage 
    UIGraphicsBeginImageContextWithOptions(webView.frame.size, false, 0.0) 
    webView.drawViewHierarchyInRect(webView.frame, afterScreenUpdates: true) 
    let snapshot = UIGraphicsGetImageFromCurrentImageContext() 
    view = UIImageView(image: snapshot) 
    view.frame = webView.frame 
} 

私はデバイスとシミュレータの両方でテストしています。

編集

ここ

private func createDispatchTime(seconds: Double) -> dispatch_time_t{ 
    let delay = seconds * Double(NSEC_PER_SEC) 
    return dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) 
} 

編集#2

を派遣時間を作成するための機能私は https://gist.github.com/christopherhelf/1640454bcace39a87c93#file-wkwebviewplus-swift

信じてより良い方法を示し要旨を作成

私はwebviews UIScrollviewのsetContentSize関数を置き換え、親クラスに変更が加えられたことを通知します。

+0

私はあなたのスウィズルメソッドの実装を試みました。 WebViewが実際にWikipediaのような非常に高速なWebページをレンダリングする前にも、これも解消されます – shrutim

+0

遅延された関数を呼び出すか、setContentSizeを上書きするのではなくcontentSizeプロパティを見ることができます。これはサイズの変化を検出するために働くと思われますが、変化がないにもかかわらず通常のアニメーションサイクルでも発火するようです。 –

+0

これは間違いなく最高の答えの一つです。 メインコンテンツが読み込まれたときにiOS WebView didFinishLoadが呼び出されますが、iOS WebKitにはJavascriptの信頼できるコントロールがありません。 問題はここにあります。メインコンテンツが読み込まれていますが、まだ動作しているJavaScript(e.t.cの読み込み、リダイレクト)とWebKitではそれを追跡できません。 解決策は、すべてのデータがロードされたときにjavascriptのWebコンテンツを制御し、スクリプトメッセージを呼び出すことです。 私は[https://github.com/marcuswestin/WebViewJavascriptBridge](WebViewJavascriptBridge)を使っています。 – user2557885

関連する問題