Help us understand the problem. What is going on with this article?

WKWebViewでtarget="_blank"なリンクが開かない時の対処法

More than 3 years have passed since last update.

普通にWKWebViewを実装したらtarget="_blank"なリンクが押されたときに無反応になるので対処してみました。別の回避方法がありましたらコメント欄にて教えて下さい。

ついでにアプリリンク(iTunes)や他アプリへのURL Schemeの対応も書いています。

(※ WKNavigationDelegateプロトコルとwebView.navigationDelegate = selfとすることをお忘れなく。)

Swift 3.0版

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    guard let url = navigationAction.request.url else {
        decisionHandler(.cancel)
        return
    }

    if url.absoluteString.range(of: "//itunes.apple.com/") != nil {
        if UIApplication.shared.responds(to: #selector(UIApplication.open(_:options:completionHandler:))) {
            UIApplication.shared.open(url, options: [UIApplicationOpenURLOptionUniversalLinksOnly:false], completionHandler: { (finished: Bool) in
            })
        }
        else {
            // iOS 10 で deprecated 必要なら以降のopenURLも振り分ける
            // iOS 10以降は UIApplication.shared.open(url, options: [:], completionHandler: nil)
            UIApplication.shared.openURL(url)
        }
        decisionHandler(.cancel)
        return
    }
    else if !url.absoluteString.hasPrefix("http://")
        && !url.absoluteString.hasPrefix("https://") {
        // URL Schemeをinfo.plistで公開しているアプリか確認
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.openURL(url)
            decisionHandler(.cancel)
            return
        }
        //                // 確認せずとりあえず開く
        //                UIApplication.shared.openURL(url)
        //                decisionHandler(.cancel)
        //                return
    }

    switch navigationAction.navigationType {
    case .linkActivated:
        if navigationAction.targetFrame == nil
            || !navigationAction.targetFrame!.isMainFrame {
            // <a href="..." target="_blank"> が押されたとき
            webView.load(URLRequest(url: url))
            decisionHandler(.cancel)
            return
        }
    case .backForward:
        break
    case .formResubmitted:
        break
    case .formSubmitted:
        break
    case .other:
        break
    case .reload:
        break
    } // 全要素列挙した場合はdefault不要 (足りない要素が追加されたときにエラーを吐かせる目的)

    decisionHandler(.allow)
}

別法

コメント欄に @taketo1024 さんが書いてくださった方法のSwift 3.0版です。
(※ 上記はプロトコルWKNavigationDelegatewebView.navigationDelegate = selfを指定することで動きますが、こちらはWKUIDelegatewebView.uiDelegate = selfと指定します。)

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    guard let url = navigationAction.request.url else {
        return nil
    }

    guard let targetFrame = navigationAction.targetFrame, targetFrame.isMainFrame else {
        webView.load(URLRequest(url: url))
        return nil
    }
    return nil
}

Objective-C

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSURL *url = navigationAction.request.URL;

    // iTunes: アプリのリンクなど
    if ([url.absoluteString rangeOfString:@"//itunes.apple.com/"].location != NSNotFound) {
        [[UIApplication sharedApplication] openURL:url];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    // http(s) 以外のプロトコル: 他のアプリへ移動する場合
    else if (![url.absoluteString hasPrefix:@"http://"]
             && [url.absoluteString hasPrefix:@"https://"]) {
        // URL Schemeをinfo.plistで公開しているかを確認
        // if ([[UIApplication sharedApplication] canOpenURL:url]]) {
        //     [[UIApplication sharedApplication] openURL:url];
        //     decisionHandler(WKNavigationActionPolicyCancel);
        // }
        // or 確認せず開く
        [[UIApplication sharedApplication] openURL:url];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }

    switch (navigationAction.navigationType) {
        case WKNavigationTypeLinkActivated: {
            NSLog(@"WKNavigationTypeLinkActivated::");
            // <a href="..." target="_blank"> が押されたとき
            if (!navigationAction.targetFrame
                || !navigationAction.targetFrame.isMainFrame) {
                [webView loadRequest:[NSURLRequest requestWithURL:url]];
                decisionHandler(WKNavigationActionPolicyCancel);
                return;
            }
            break;
        }
        case WKNavigationTypeFormSubmitted: {
            NSLog(@"WKNavigationTypeFormSubmitted::");
            break;
        }
        case WKNavigationTypeBackForward: {
            NSLog(@"WKNavigationTypeBackForward::");
            break;
        }
        case WKNavigationTypeReload: {
            NSLog(@"WKNavigationTypeReload::");
            break;
        }
        case WKNavigationTypeFormResubmitted: {
            NSLog(@"WKNavigationTypeFormResubmitted::");
            break;
        }
        case WKNavigationTypeOther: {
            NSLog(@"WKNavigationTypeOther::");
            break;
        }
    } // 全要素列挙した場合はdefault不要 (足りない要素が追加されたときにエラーを吐かせる目的)

    decisionHandler(WKNavigationActionPolicyAllow);
}
ShingoFukuyama
[GitHub: https://goo.gl/gDtSXW] [Twitter: https://goo.gl/B6S8Zc]
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした