实际显示视图时出现WKWebView通知 [英] WKWebView notification when view is actually shown

查看:88
本文介绍了实际显示视图时出现WKWebView通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对 WKWebView 进行截图.我在网络视图加载完成后立即调用方法 drawViewHierarchyInRect (屏幕更新设置为 true )-为此,我观察了 loading 属性网络视图.但是,我注意到,在Web视图通知我加载完成时,它实际上并未在屏幕上显示.这就是为什么屏幕截图始终仅是白色的原因.当我在加载后0.5秒(显然太长)后截取屏幕截图时,屏幕截图显示了所需的结果.我的问题是:我不知道网络视图何时真正显示在屏幕上,我可以将延迟设置为0.05,但是我不能百分百确定每次都可以.因此,我的问题是:当实际显示Web视图并且准备好截图时,如何通知我.

I want to take a screenshot of a WKWebView. I call the method drawViewHierarchyInRect (with screen updates set to true) right after the web view finished loading - for this purpose I observe the loading property of the web view. However, I noticed, that at the time the web view notifies me that loading has finished, it doesn't actually display itself on the screen. That's why the screenshot is always only white. When I take the screenshot 0.5 seconds after loading (which is obviously too long) the screenshot shows the desired result. My problem is: I don't know when the web view actually displays itself on the screen, I could set the delay to 0.05 probably but I can't be a 100% sure it works every time. My question is therefore: How can I be notified when the web view is actually displayed an is ready for a screenshot.

提前谢谢!

顺便说一句:我正在将Swift 2.0和iOS 9与Xcode 7(正式发行版)一起使用

BTW: I'm using Swift 2.0 and iOS 9 with Xcode 7 (official release)

推荐答案

正如我刚刚做的那样,请让我知道我尝试了什么以及如何解决.我尝试了几件事,首先是WKUserScript

as I've just worked on this, let me know what I tried and how I figured it out. I tried a couple of things, first, a WKUserScript

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

在状态"名称空间上.理论上,这将等待所有内容加载,然后调用WKScriptMessageHandler

on the "status" namespace. This theoretically waits for all contents to be loaded, and then calls the WKScriptMessageHandler

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

通过

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

我认为一切准备就绪.有时但并非总是有效.

where I thought everything would be ready. Worked sometimes, but not always.

像您一样,我也尝试添加WKNavigationDelegate并使用

As you, I've also tried adding a WKNavigationDelegate and using

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

同样,这没有用.此外,为估算的Progress值添加观察者

Again, this didn't work. Also, adding an observer for the estimatedProgress value

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

然后尝试在

override func observeValueForKeyPath(keyPath: String?, ofObject: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { }

没用.

但是,有效的方法是定期检查webView的内容大小.我已经在WKUserScript调用的userContentController函数中进行了此操作-但您也可以在didFinishNavigation函数中进行此操作,然后只需更改将再次调用的函数即可.这里的代码:

However, what does work is to check upon the webView's content size regularly. I've did this within the userContentController function, which is called by the WKUserScript - but you can also do this within the didFinishNavigation function, and then simply change the function which is to be called again. Here the code:

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秒再次调用该方法,直到设置了该属性.这是我用来创建屏幕截图的功能

This essentially checks on the contentSize height property and if it's zero, it will call the method again every 0.01 seconds until the property is set. Here are the functions I used for creating the screenshot

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
}

我已经在设备和模拟器上对其进行了测试,并且可以正常工作.

I've tested it on both device and simulator and it works.

修改

这里是创建调度时间的功能

Here the function for creating the dispatch time

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

I created a gist which shows an even better way I believe https://gist.github.com/christopherhelf/1640454bcace39a87c93#file-wkwebviewplus-swift

我替换了webviews UIScrollview的setContentSize函数,并通知父类已进行了更改.

I replaced the setContentSize function of the webviews UIScrollview and notify the parent class that a change has been made.

这篇关于实际显示视图时出现WKWebView通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆