ios WKWebView 在 safari 中打开来自某个域的链接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36231061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:45:55  来源:igfitidea点击:

WKWebView open links from certain domain in safari

iosswiftsafariwkwebview

提问by Greg Williams

Within my app I am want to open links from within mydomain (e.g.: communionchapelefca.org) in WKWebView but then have links from otherdomains (e.g.: google.com) open in Safari. I would prefer to do this programmatically.

在我的应用程序中,我想在 WKWebView 中打开来自我的域(例如:communonchapelefca.org)中的链接,然后在 Safari 中打开来自其他域(例如:google.com)的链接。我更愿意以编程方式执行此操作。

I have found a few solutions on Stack overflow (here, here, here, and here) but they all seem to be Obj-C based and I am looking for a solution using Swift.

我找到了一些关于堆栈溢出的解决方案(这里这里这里这里),但它们似乎都是基于 Obj-C 的,我正在寻找使用 Swift 的解决方案。

ViewController.swift:

视图控制器.swift:

import UIKit
import WebKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let myWebView:WKWebView = WKWebView(frame: CGRectMake(0, 0,   UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height))

        myWebView.loadRequest(NSURLRequest(URL: NSURL(string: "http://www.communionchapelefca.org/app-home")!))

        self.view.addSubview(myWebView)

回答by Leo Dabus

You can implement WKNavigationDelegate, add the decidePolicyForNavigationActionmethod and check there the navigationType and requested url. I have used google.combelow but you can just change it to your domain:

您可以实现WKNavigationDelegate、添加decidePolicyForNavigationAction方法并检查导航类型和请求的 url。我在下面使用了google.com,但您可以将其更改为您的域:

Xcode 8.3 ? Swift 3.1 or later

Xcode 8.3?Swift 3.1 或更高版本

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    let webView = WKWebView()

    override func viewDidLoad() {
        super.viewDidLoad()

        webView.frame = view.bounds
        webView.navigationDelegate = self

        let url = URL(string: "https://www.google.com")!
        let urlRequest = URLRequest(url: url)

        webView.load(urlRequest)
        webView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        view.addSubview(webView)
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if navigationAction.navigationType == .linkActivated  {
            if let url = navigationAction.request.url,
                let host = url.host, !host.hasPrefix("www.google.com"),
                UIApplication.shared.canOpenURL(url) {
                UIApplication.shared.open(url)
                print(url)
                print("Redirected to browser. No need to open it locally")
                decisionHandler(.cancel)
            } else {
                print("Open it locally")
                decisionHandler(.allow)
            }
        } else {
            print("not a user click")
            decisionHandler(.allow)
        }
    }
}

回答by Gianfranco Lemmo

For Swift 3.0

对于 Swift 3.0

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {
    let wv = WKWebView(frame: UIScreen.main.bounds)
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let url =  NSURL(string: "https://www.google.com") else { return }
        wv.navigationDelegate = self
        wv.load(NSURLRequest(url: url as URL) as URLRequest)
        view.addSubview(wv)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if navigationAction.navigationType == .LinkActivated  {
            if let newURL = navigationAction.request.url,
                let host = newURL.host , !host.hasPrefix("www.google.com") &&
                UIApplication.shared.canOpenURL(newURL) &&
                UIApplication.shared.openURL(newURL) {
                    print(newURL)
                    print("Redirected to browser. No need to open it locally")
                    decisionHandler(.cancel)
            } else {
                print("Open it locally")
                decisionHandler(.allow)
            }
        } else {
            print("not a user click")
            decisionHandler(.allow)
        }
    }
}

回答by headstream

Here is sample code from the response to the swift written in obj c.

以下是对用 obj c 编写的 swift 的响应的示例代码。

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler
{
    if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
        if (navigationAction.request.URL) {
            NSLog(@"%@", navigationAction.request.URL.host);
            if (![navigationAction.request.URL.resourceSpecifier containsString:@"ex path"]) { 
                if ([[UIApplication sharedApplication] canOpenURL:navigationAction.request.URL]) {
                    [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
                    decisionHandler(WKNavigationActionPolicyCancel);
                }
            } else {
                decisionHandler(WKNavigationActionPolicyAllow);
            }
        }
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

回答by Andy G

Swift 4 update for George Vardikos answer:

George Vardikos 的 Swift 4 更新回答:

public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let url = navigationAction.request.url
        guard url != nil else {
            decisionHandler(.allow)
            return
        }

        if url!.description.lowercased().starts(with: "http://") ||
            url!.description.lowercased().starts(with: "https://")  {
            decisionHandler(.cancel)
            UIApplication.shared.open(url!, options: [:], completionHandler: nil)
        } else {
            decisionHandler(.allow)
        }
}

回答by Code Different

Make a function to decide where to load the URL:

创建一个函数来决定在哪里加载 URL:

func loadURLString(str: String) {
    guard let url = NSURL(string: str) else {
        return
    }

    if url.host == "www.communionchapelefca.org" {
        // Open in myWebView
        myWebView.loadRequest(NSURLRequest(URL: url))
    } else {
        // Open in Safari
        UIApplication.sharedApplication().openURL(url)
    }
}

Usage:

用法:

loadURLString("http://www.communionchapelefca.org/app-home") // Open in myWebView
loadURLString("http://www.apple.com") // Open in Safari

回答by George Vardikos

My swift 3 solution:

我的 swift 3 解决方案:

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

        let url = navigationAction.request.url

        if url?.description.lowercased().range(of: "http://") != nil || url?.description.lowercased().range(of: "https://") != nil {
            decisionHandler(.cancel)
            UIApplication.shared.openURL(url!)
        } else {
            decisionHandler(.allow)
        }

    }

Do not forget also to setup te delegate

也不要忘记设置 te 委托

    public override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view = webView
    }