为什么WKWebView没有打开target ="_ blank"的链接?

stk*_*stk 104 ios wkwebview

WKWebView不打开任何target="_blank"在HTML <a href>-Tag中也称为"在新窗口中打开"属性的链接.

Clo*_* Xu 159

我的解决方案是取消导航并再次使用loadRequest加载请求.这将是类似于UIWebView的行为,它始终在当前帧中打开新窗口.

首先,您需要实现WKUIDelegate.并将其设置为_webview.UIDelegate.然后执行:

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{

  if (!navigationAction.targetFrame.isMainFrame) {

    [webView loadRequest:navigationAction.request];
  }

  return nil;
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案对我有用.不要忘记设置`UIDelegate`属性,因为这个方法在`WKUIDelegate`中声明而不是`WKNavigationDelegate`. (4认同)
  • @ChristopherPickslay在我的WKWebView中使用此方法时,请求网址始终为空白,因此webview会指向空白页面,任何想法? (4认同)
  • 这是正确的答案.我们尝试了接受的答案但没有成功.但是@ Cloud的答案是有效的,并且[在dev论坛上的这个回复](https://devforums.apple.com/message/1059229#1059229)解释了原因. (3认同)

Bil*_*man 59

来自@Cloud Xu的答案是正确的答案.仅供参考,这里是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
}
Run Code Online (Sandbox Code Playgroud)

  • 如果你想在Safari中打开它,你会怎么写呢?另外,我需要在视图控制器中引用什么才能使其工作? (2认同)

muh*_*urk 43

使用最新版本的Swift 4.2+

import WebKit
Run Code Online (Sandbox Code Playgroud)

使用WKUIDelegate扩展您的课程

为webview设置委托

self.webView.uiDelegate = self
Run Code Online (Sandbox Code Playgroud)

实施协议方法

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

  • 请任何人都可以帮助我,我已将委托 uiDelegate 分配给 wkwebview 但其方法创建带有配置的 Web 视图未被调用 (2认同)

stk*_*stk 23

将自己添加为WKNavigationDelegate

_webView.navigationDelegate = self;
Run Code Online (Sandbox Code Playgroud)

并在委托回调decisionPolicyForNavigationAction: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);
}
Run Code Online (Sandbox Code Playgroud)

PS:这段代码来自我的小项目STKWebKitViewController,它围绕WKWebView包装了一个可用的UI.


Min*_*int 16

Cloud xu的答案解决了我的问题。

如果有人需要等效的 Swift(4.x/5.0) 版本,这里是:

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if let frame = navigationAction.targetFrame,
        frame.isMainFrame {
        return nil
    }
    // for _blank target or non-mainFrame target
    webView.load(navigationAction.request)
    return nil
}
Run Code Online (Sandbox Code Playgroud)

当然你webView.uiDelegate要先设置。


小智 12

如果您已经设置了WKWebView.navigationDelegate

WKWebView.navigationDelegate = self;

你只需要实现:

- (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);
}
Run Code Online (Sandbox Code Playgroud)

这样您就不需要实现WKUIDelegate方法了.


Ugo*_*lli 8

这些解决方案都不适合我,我确实解决了这个问题:

1)实现WKUIDelegate

@interface ViewController () <WKNavigationDelegate, WKUIDelegate>
Run Code Online (Sandbox Code Playgroud)

2)设置wkWebview的UIDelegate委托

self.wkWebview.UIDelegate = self;
Run Code Online (Sandbox Code Playgroud)

3)实现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;  }
Run Code Online (Sandbox Code Playgroud)


Oli*_*ang 7

我确认Bill Weinman的Swift代码是正确的.但是需要提一下,你还需要委托UIDelegate才能使用它,以防你不熟悉像我这样的iOS开发人员.

像这样的东西:

self.webView?.UIDelegate = self
Run Code Online (Sandbox Code Playgroud)

因此,有三个地方需要进行更改.


Dav*_*d H 5

您还可以推送另一个视图控制器,或打开一个新选项卡等:

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
}
Run Code Online (Sandbox Code Playgroud)