目标:在网站加载完成后获取WKWebView的屏幕截图
采用的方法:
创建一个名为screen capture()的扩展方法,该方法获取WKWebView的图像
让我的UIViewController实现WKNavigationDelegate
设置wkwebview.navigationDelegate = self(在UIViewController初始化中)
在UIViewcontroller中实现didFinishNavigation委托func,为WKWebView调用屏幕捕获扩展方法
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) { let img = webView.screenCapture() }
问题:
我在这里缺少什么?我查看了WKWebView的所有可能的委托函数,没有其他任何东西似乎代表WKWebView中内容加载的完成。如果有解决方法,将不胜感激。
更新:添加我用来截取网页视图截图的截图代码
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
}
答案 0 :(得分:22)
对于那些仍在寻找答案的人来说,明确的答案是BS,他只是强迫他的方式让它被接受。
“loading”和webView(webView:WKWebView,didFinishNavigation navigation:WKNavigation!)都做同样的事情,表明主资源是否已加载。现在这并不意味着整个网页/网站都被加载,因为它实际上取决于网站的实施。如果需要加载脚本和资源(图像,字体等)使其自身可见,导航完成后仍然看不到任何内容,因为webview不会跟踪网站发出的网络调用,只有导航是跟踪,所以它不会真正知道什么时候网站完全加载。
答案 1 :(得分:14)
当内容加载完成时,WKWebView不会使用委托来告诉您(这就是为什么您找不到适合您目的的委托方法)。知道WKWebView是否仍在加载的方法是使用KVO(键值观察)来查看其loading
属性。这样,当loading
从true
更改为false
时,您会收到通知。
这是一个循环动画gif,显示我测试时会发生什么。我加载了一个Web视图,并通过KVO响应其loading
属性来拍摄快照。上部视图是Web视图;较低(压扁)的视图是快照。如您所见,快照确实捕获了加载的内容:
答案 2 :(得分:9)
以下是我解决它的方法:
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
}
}
答案 3 :(得分:3)
这里有很多建议,可以解决不完整的问题。观察者对“正在加载”并不可靠,因为当它切换为“否”时,布局尚未发生,并且您无法准确读取页面大小。
视实际页面内容而定,将JS注入视图以报告页面大小也会有问题。
WKWebView显然使用了滚动器(确切地说是“ WKWebScroller”子类)。因此,最好的选择是监视该滚动条的contentSize。
- (void) viewDidLoad {
//...super etc
[self.webKitView.scrollView addObserver: self
forKeyPath: @"contentSize"
options: NSKeyValueObservingOptionNew
context: nil];
}
- (void) dealloc
{
// remove observer
[self.webKitView.scrollView removeObserver: self
forKeyPath: @"contentSize"];
}
- (void) observeValueForKeyPath: (NSString*) keyPath
ofObject: (id) object
change: (NSDictionary<NSKeyValueChangeKey,id>*) change
context: (void*) context
{
if ([keyPath isEqualToString: @"contentSize"])
{
UIScrollView* scroller = (id) object;
CGSize scrollFrame = scroller.contentSize;
NSLog(@"scrollFrame = {%@,%@}",
@(scrollFrame.width), @(scrollFrame.height));
}
}
当心contentSize:它被触发了很多。如果将webView嵌入到另一个滚动区域中(例如,将其用作表单元素),则在滚动整个视图时,该子视图webView将触发相同值的更改。因此,使您不必不必要地调整大小或引起不必要的刷新。
此解决方案在High Sierra XCode 10上的iPad Air 2 sim上的iOS 12上进行了测试。
答案 4 :(得分:1)
检查页面内容是从swift还是objective-c加载,尤其是对于包含许多动态内容的非常复杂的页面,这不是一个好的选择。
通过网页的javascript通知您ios代码的更好方法。这使得它非常灵活和有效,您可以在加载dom或页面时通知ios代码。
您可以在此处查看我的 post 以获取更多信息。
答案 5 :(得分:0)
您可以将JavaScript注入Web视图中,以等待onDOMContentLoaded或检查document.readyState状态。我有一个应用程序已经这样做了多年,这是等待DOM填充的唯一可靠方法。如果需要加载所有图像和其他资源,则需要使用JavaScript等待加载事件。这是一些文档:
https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState