WKWebView没有完成加载,当didFinishNavigation被调用 – 在WKWebView中的错误?

目标:在网站加载完成后截取WKWebView

采用的方法:

  • 在UIViewController中定义了一个WKWebView var
  • 创build了一个名为screen capture()的扩展方法,它可以获取WKWebView的图像

  • 使我的UIViewController实现WKNavigationDelegate

  • 设置wkwebview.navigationDelegate = self(在UIViewController init中)

  • 在UIViewcontroller中实现了didFinishNavigation委托func来调用WKWebView的屏幕截图扩展方法

func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) { let img = webView.screenCapture() } 

问题:

  • 当我debugging我模拟器,我注意到控制达到didFinishNavigation()func,即使网站还没有在WKWebView呈现
  • 相应地,所拍摄的图像截图是一个白色的斑点。

我在这里错过了什么? 我查看了WKWebView的所有可能的委托function,而没有其他东西看起来代表WKWebView中内容加载的完成。 如果有解决办法,将不胜感激


更新:添加我正在使用的截图代码为Web视图截图

 class func captureEntireUIWebViewImage(webView: WKWebView) -> UIImage? { var webViewFrame = webView.scrollView.frame if (webView.scrollView.contentSize != CGSize(width: 0,height: 0)){ webView.scrollView.frame = CGRectMake(webViewFrame.origin.x, webViewFrame.origin.y, webView.scrollView.contentSize.width, webView.scrollView.contentSize.height) UIGraphicsBeginImageContextWithOptions(webView.scrollView.contentSize, webView.scrollView.opaque, 0) webView.scrollView.layer.renderInContext(UIGraphicsGetCurrentContext()) var image:UIImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() webView.scrollView.frame = webViewFrame return image } return nil } 

WKWebView不使用委托让你知道什么时候内容加载完成(这就是为什么你找不到适合你的目的的委托方法)。 知道WKWebView是否还在加载的方法是使用KVO(键值观察)来观察它的loading属性。 这样,您将从true更改为false时收到通知。

这里有一个循环的animationgif显示当我testing这个时会发生什么。 我加载一个Web视图,并通过KVO来响应其loading属性来拍摄快照。 上部视图是Web视图; 较低的(压扁的)视图是快照。 如您所见,快照确实捕获加载的内容:

在这里输入图像说明

这是我如何解决它:

 class Myweb: WKWebView { func setupWebView(link: String) { let url = NSURL(string: link) let request = NSURLRequest(URL: url!) loadRequest(request) addObserver(self, forKeyPath: "loading", options: .New, context: nil) } override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { guard let _ = object as? WKWebView else { return } guard let keyPath = keyPath else { return } guard let change = change else { return } switch keyPath { case "loading": if let val = change[NSKeyValueChangeNewKey] as? Bool { if val { } else { print(self.loading) //do something! } } default:break } } deinit { removeObserver(self, forKeyPath: "loading") } } 

更新Swift 3.1

 override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard let _ = object as? WKWebView else { return } guard let keyPath = keyPath else { return } guard let change = change else { return } switch keyPath { case "loading": if let val = change[NSKeyValueChangeKey.newKey] as? Bool { //do something! } default: break } } 

对于那些仍然在寻找答案的人来说,标记的答案是BS,他只是强迫他接受。
“加载”和webView(webView:WKWebView,didFinishNavigation导航:WKNavigation!)都做同样的事情,指示主资源是否加载。 现在这并不意味着整个网页/网站被加载,因为它确实取决于网站的实施。 如果需要加载脚本和资源(图像,字体等)以使其可见,导航完成后仍然不会看到任何内容,因为网站所做的networking调用不会被webview跟踪,只有导航是跟踪,所以它不会真正知道什么时候网站加载完全。

检查从swift或objective-c加载的页面内容是不是一个好的select,特别是对于具有许多dynamic内容的非常复杂的页面。

一个更好的方式来通知你从网页的JavaScript代码。 这使得它非常灵活和有效,当一个dom或页面被加载时,你可以通知ios代码。

你可以在这里查看我的post以获取更多信息。

所以这些答案都没有为我工作。 这是什么工作。

我使用webView作为我的WKWebView的名称。 改变你用什么。

我用Swift Spinner

这在整个屏幕上创build了一个很好的叠加半透明模式。 加载它在viewDidLoad中是这样的:

 SwiftSpinner.show("Doing something cool....") 

使用观察者停止如下:

首先,在你的webview方法中join这个…你加载你的URL的地方:

  webView?.addObserver(self, forKeyPath: #keyPath(WKWebView.loading), options: .new, context: nil) 

这用于观察者:

 // To handle spinner stop; was testing other stuff, could simplify override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard let wv = object as? WKWebView else { return } guard let keyPath = keyPath else { return } guard let change = change else { return } print("in observer") switch keyPath { case "loading": // new:1 or 0 if let val = change[.newKey] as? Bool { if val { print("starting animating") /// spinner.startAnimating() } else { if wv.estimatedProgress == 1 { print("finished loading! stop animating spinner") SwiftSpinner.hide() } } } default: break