Как рассчитать высоту контента WKWebView?

Для UIWebView мы можем получить высоту контента следующим образом:

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

Но WKWebView не имеет этого метода, а webView.scrollView.contentSize.height не прав.

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

Благодарим за помощь!

4 ответа

Я решил эту проблему с KVO.

Во-первых, addObserver для WKWebView scrollView contentSize вот так:

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

И далее, получите изменение следующим образом:

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.
 }
 }
}
</void>

Легко получить высоту контента веб-просмотра.

Не забудьте удалить наблюдателя:

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

Я прокручиваю эту строку в deinit.


EDIT:

Чтобы получить наилучший возможный расчет высоты, в конце я сделал несколько вещей, чтобы получить максимальную высоту:

  • Я установил размер веб-представления действительно большим, а затем загрузил содержимое.
  • После загрузки содержимого (уведомление KVO) я изменяю размер представления, используя метод ниже.
  • Затем я снова запустил функцию размера , и я получил новый размер и изменил размер моего представления еще раз.

Вышеприведенные результаты получили самые точные результаты для меня.

ORIGINAL:

Я пробовал просмотр прокрутки KVO, и я попытался оценить javascript в документе, используя clientHeight, offsetHeight и т.д.

Что со мной в конечном итоге получилось: document.body.scrollHeight. Или используйте scrollHeight вашего верхнего элемента, например. контейнер div.

Я слушаю изменения свойств loading WKWebview с помощью KVO:

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

И затем:

- (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];
 }
 }
}
</nskeyvaluechangekey,id>

Реализация updateWebviewFrame:

[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;
}];


Вы можете сделать это следующим образом:

self.webview.navigationDelegate = self;
- (void)webView:(WKWebView *)webview didFinishNavigation:(WKNavigation *)navigation{
 // webview.scrollView.contentSize will equal {0,0} at this point so wait
 [self checkIfWKWebViewReallyDidFinishLoading];
}
- (void)checkIfWKWebViewReallyDidFinishLoading{
 _contentSize = _webview.scrollView.contentSize;
 if (_contentSize.height == 0){
 [self performSelector:@selector(WKWebViewDidFinishLoading) withObject:nil afterDelay:0.01];
 }
}


WKWebView не завершил загрузку, когда вызывается функцияFinishNavigation - ошибка в WKWebView? WKWebView не использует делегирование, чтобы вы знали, когда загрузка контента завершена. Вы можете создать новый поток, чтобы проверить статус WKWebView.

override func viewDidLoad() {
 super.viewDidLoad()
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), { 
 while(self.webView?.loading == true){
 sleep(1)
 } 
 dispatch_async(dispatch_get_main_queue(), {
 print(self.webView!.scrollView.contentSize.height)
 })
 })
}

licensed under cc by-sa 3.0 with attribution.