undeclared type support previous example broken before ios wkwebview

ios - type - ¿Por qué WKWebView no abre enlaces con target="_ blank"?



wkwebview before ios 11.0(nscoding support was broken in previous versions) (11)

WKWebView no abre ningún enlace que tenga el atributo "Abrir en una nueva ventana" de target="_blank" en su HTML <a href> -Tag.


Solución

allen huang contesta

Detalles

Xcode 9.2, Swift 4

Muestra completa con enlaces de target = "_ blank"

import UIKit import WebKit class ViewController: UIViewController { var urlString = "http://google.com" var webView: WKWebView! fileprivate var webViewIsInited = false override func viewDidLoad() { super.viewDidLoad() } override func viewWillLayoutSubviews() { if !webViewIsInited { webViewIsInited = true if webView == nil { webView = WKWebView(frame: UIScreen.main.bounds, configuration: WKWebViewConfiguration()) } view.addSubview(webView) webView.navigationDelegate = self webView.uiDelegate = self webView.loadUrl(string: urlString) } } } extension ViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { decisionHandler(.allow) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { if let host = webView.url?.host { self.navigationItem.title = host } } } extension ViewController: WKUIDelegate { func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { if navigationAction.targetFrame == nil { let vc = ViewController() vc.urlString = navigationAction.request.url?.absoluteString ?? "http://google.com" vc.view.frame = UIScreen.main.bounds vc.webView = WKWebView(frame: UIScreen.main.bounds, configuration: configuration) navigationController?.pushViewController(vc, animated: false) return vc.webView } return nil } } extension WKWebView { func loadUrl(string: String) { if let url = URL(string: string) { if self.url?.host == url.host { self.reload() } else { load(URLRequest(url: url)) } } } }


Agregue usted mismo como WKNavigationDelegate

_webView.navigationDelegate = self;

e implemente el siguiente código en la devolución de llamada delegada decidePolicyForNavigationAction: decisionHandler:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { //this is a ''new window action'' (aka target="_blank") > open this URL externally. If we´re doing nothing here, WKWebView will also just do nothing. Maybe this will change in a later stage of the iOS 8 Beta if (!navigationAction.targetFrame) { NSURL *url = navigationAction.request.URL; UIApplication *app = [UIApplication sharedApplication]; if ([app canOpenURL:url]) { [app openURL:url]; } } decisionHandler(WKNavigationActionPolicyAllow); }

PD: Este código es de mi pequeño proyecto github.com/sticksen/STKWebKitViewController , que envuelve una interfaz de usuario utilizable alrededor de WKWebView.


Confirmo que el código Swift de Bill Weinman es correcto. Pero debo mencionar que también debe delegar UIDelegate para que funcione, en caso de que sea nuevo en el desarrollo de iOS como yo.

Algo como esto:

self.webView?.UIDelegate = self

Entonces hay tres lugares en los que necesitas hacer cambios.


Encontré algunos problemas que no se pueden resolver utilizando simplemente webView.load(navigationAction.request) . Así que uso crear una nueva vista web para hacer y simplemente funciona bien.

//MARK:- WKUIDelegate func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { NSLog(#function) if navigationAction.targetFrame == nil { NSLog("=> Create a new webView") let webView = WKWebView(frame: self.view.bounds, configuration: configuration) webView.uiDelegate = self webView.navigationDelegate = self self.webView = webView return webView } return nil }


Esto funcionó para mí:

-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures { if (!navigationAction.targetFrame.isMainFrame) { WKWebView *newWebview = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration]; newWebview.UIDelegate = self; newWebview.navigationDelegate = self; [newWebview loadRequest:navigationAction.request]; self.view = newWebview; return newWebview; } return nil; } - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { decisionHandler(WKNavigationActionPolicyAllow); } - (void)webViewDidClose:(WKWebView *)webView { self.view = self.webView; }

Como puede ver, lo que hacemos aquí es simplemente abrir una nueva vista webView con la nueva URL y controlar la posibilidad de que se cierre, solo si necesita una respuesta de esa second webview para que se muestre en la primera.


La respuesta de @Cloud Xu es la respuesta correcta. Sólo para referencia, aquí está en Swift:

// this handles target=_blank links by opening them in the same view func webView(webView: WKWebView!, createWebViewWithConfiguration configuration: WKWebViewConfiguration!, forNavigationAction navigationAction: WKNavigationAction!, windowFeatures: WKWindowFeatures!) -> WKWebView! { if navigationAction.targetFrame == nil { webView.loadRequest(navigationAction.request) } return nil }


Mi solución es cancelar la navegación y cargar la solicitud con loadRequest: nuevamente. Este será el comportamiento similar a UIWebView, que siempre abre una nueva ventana en el marco actual.

Primero necesitas tener una implementación de WKUIDelegate . Y _webview.UIDelegate en _webview.UIDelegate . Luego implementa:

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures { if (!navigationAction.targetFrame.isMainFrame) { [webView loadRequest:navigationAction.request]; } return nil; }


Ninguna de esas soluciones funcionó para mí, resolví el problema por:

1) Implementando WKUIDelegate

@interface ViewController () <WKNavigationDelegate, WKUIDelegate>

2) Configuración del delegado UIDelegate de wkWebview

self.wkWebview.UIDelegate = self;

3) Implementando el método createWebViewWithConfiguration

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures { if (!navigationAction.targetFrame.isMainFrame) { [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; [[UIApplication sharedApplication] openURL:[navigationAction.request URL]]; } return nil; }


Para usar la última versión de Swift 4.2+

import WebKit

Extiende tu clase con WKUIDelegate

Establecer delegado para webview

self.webView.uiDelegate = self

Implementar el método de protocolo.

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { if navigationAction.targetFrame == nil { webView.load(navigationAction.request) } return nil }


Si ya ha configurado el WKWebView.navigationDelegate

WKWebView.navigationDelegate = self;

solo necesitas implementar:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { BOOL shouldLoad = [self shouldStartLoadWithRequest:navigationAction.request]; // check the url if necessary if (shouldLoad && navigationAction.targetFrame == nil) { // WKWebView ignores links that open in new window [webView loadRequest:navigationAction.request]; } // always pass a policy to the decisionHandler decisionHandler(shouldLoad ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel); }

de esta manera no es necesario implementar el método WKUIDelegate.


También puede presionar otro controlador de vista, o abrir una nueva pestaña, etc.

func webView(webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration, forNavigationAction navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { var wv: WKWebView? if navigationAction.targetFrame == nil { if let vc = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as? ViewController { vc.url = navigationAction.request.URL vc.webConfig = configuration wv = vc.view as? WKWebView self.navigationController?.pushViewController(vc, animated: true) } } return wv }