ios - support - wkwebview navigation swift
WKWebView no terminó de cargarse, cuando se llamó a FinNavegación-¿Error en WKWebView? (5)
Objetivo: tomar una captura de pantalla de WKWebView después de que el sitio web haya terminado de cargarse
Método empleado:
- Definió una var WKWebView en UIViewController
Creado un método de extensión llamado captura de pantalla () que toma la imagen de WKWebView
Hice mi UIViewController para implementar WKNavigationDelegate
Establezca wkwebview.navigationDelegate = self (en el init de UIViewController)
Implementé la función de delegación didFinishNavigation en UIViewcontroller para llamar al método de extensión de captura de pantalla para WKWebView
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) { let img = webView.screenCapture() }
Preguntas:
- Cuando depuro el simulador, noto que el control alcanza el funcion didFinishNavigation () a pesar de que el sitio web aún no se ha procesado en WKWebView
- En consecuencia, la captura de pantalla de la imagen es una mancha blanca.
¿Que me estoy perdiendo aqui? Miré todas las posibles funciones de delegado para WKWebView y nada más parece representar la finalización de la carga de contenido en WKWebView. Agradecería ayuda si hay un trabajo alrededor
Actualización: Agregar el código de captura de pantalla que estoy usando para tomar una captura de pantalla para la vista 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
}
Así es como lo resolví:
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")
}
}
Actualizar 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
}
}
Entonces, ninguna de estas respuestas funcionó para mí. Aquí está lo que funcionó.
Uso webView como el nombre de mi WKWebView. Cambia a lo que usaste
Esto crea una gran superposición modal semi-transparente en toda la pantalla. Cargarlo en viewDidLoad así:
SwiftSpinner.show("Doing something cool....")
El uso del observador se detiene de la siguiente manera:
Primero, agregue esto en su método de vista web ... donde carga su URL:
webView?.addObserver(self, forKeyPath: #keyPath(WKWebView.loading), options: .new, context: nil)
Esto usa esto para el observador:
// 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
No es una buena opción verificar si el contenido de la página se cargó de forma rápida u objetiva, especialmente para páginas muy complejas con muchos contenidos dinámicos.
Una mejor manera de informarle el código ios desde el javascript de la página web. Esto lo hace muy flexible y eficaz, puede notificar el código ios cuando se carga un dom o la página.
Puedes consultar mi publicación aquí para más información.
Para aquellos que aún están buscando una respuesta a esto, la respuesta marcada es BS, él se limitó a forzar su aceptación.
"loading" y webView (webView: WKWebView, didFinishNavigation navigation: WKNavigation!) hacen lo mismo e indican si el recurso principal está cargado. Ahora eso no significa que toda la página web / sitio web está cargada, porque realmente depende de la implementación del sitio web. Si necesita cargar scripts y recursos (imágenes, fuentes, etc.) para hacerse visible, aún no verá nada después de que se complete la navegación, ya que las visitas a la red realizadas por el sitio web no son rastreadas por la vista web, solo la navegación es rastreado, por lo que no sabría realmente cuándo el sitio web se cargó por completo.
WKWebView no utiliza la delegación para informarle cuándo se completa la carga de contenido (es por eso que no puede encontrar ningún método de delegado que se adapte a su propósito). La forma de saber si un WKWebView todavía se está cargando es usar KVO (observación de valor de clave) para ver su propiedad de loading
. De esta forma, recibirá una notificación cuando loading
cambios de true
a false
.
Aquí hay un gif animado que muestra lo que sucede cuando pruebo esto. Cargué una vista web y respondo a su propiedad de loading
través de KVO para tomar una instantánea. La vista superior es la vista web; la vista inferior (aplastada) es la instantánea. Como puede ver, la instantánea captura el contenido cargado: