Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate content height of WKWebView?

Tags:

wkwebview

For UIWebView, we can get content height by this:

[webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"]

But WKWebView doesn't have this method and webView.scrollView.contentSize.height is not right.

(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
    {
    }

Thank you for your help!

like image 900
Moonlight Avatar asked Apr 21 '15 09:04

Moonlight


2 Answers

I solved this problem with KVO.

First, addObserver for WKWebView's scrollView's contentSize like this:

addObserver(self, forKeyPath: "webView.scrollView.contentSize", options: .New, context: nil)

And next, receive the change like this:

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
    if keyPath == "webView.scrollView.contentSize" {
        if let nsSize = change[NSKeyValueChangeNewKey] as? NSValue {
            let height = nsSize.CGSizeValue().height
            // Do something here using content height.
        }
    }
}

It's easy to get webview's content height.

Don't forget to remove observer:

removeObserver(self, forKeyPath: "webView.scrollView.contentSize", context: nil)

I worte this line in deinit.

like image 127
morizotter Avatar answered Oct 01 '22 01:10

morizotter


EDIT:

To get the best possible height calculation, in the end I did a few things to get the best height:

  1. I set the size of the webview to be really large and then load the content.
  2. Once the content is loaded (KVO notification) I resize the view using the method below.
  3. I then run the size function again and I get a new size and resize my view once again.

The above got the most accurate results for me.

ORIGINAL:

I've tried the scroll view KVO and I've tried evaluating javascript on the document, using clientHeight, offsetHeight, etc...

What worked for me eventually is: document.body.scrollHeight. Or use the scrollHeight of your top most element, e.g. a container div.

I listen to the loading WKWebview property changes using KVO:

[webview addObserver: self forKeyPath: NSStringFromSelector(@selector(loading)) options: NSKeyValueObservingOptionNew context: nil];

And then:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if(object == self.webview && [keyPath isEqualToString: NSStringFromSelector(@selector(loading))]) {
        NSNumber *newValue = change[NSKeyValueChangeNewKey];
        if(![newValue boolValue]) {
            [self updateWebviewFrame];
        }
    }
}

The updateWebviewFrame implementation:

[self.webview evaluateJavaScript: @"document.body.scrollHeight" completionHandler: ^(id response, NSError *error) {
     CGRect frame = self.webview.frame;
     frame.size.height = [response floatValue];
     self.webview.frame = frame;
}];
like image 43
natanavra Avatar answered Sep 30 '22 23:09

natanavra