【问题标题】:WKWebView open links from certain domain in safariWKWebView 在 safari 中打开来自某个域的链接
【发布时间】:2016-03-26 02:44:58
【问题描述】:

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

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

ViewController.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)

【问题讨论】:

    标签: ios swift safari wkwebview


    【解决方案1】:

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

    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)
            }
        }
    }
    

    【讨论】:

    • 这对我来说并不完全有效,例如,如果您转到developer.xamarin.com/visual-studio-mac,则使用该链接调用 devicePolicyForNavitationAction 两次,第一次使用 .LinkActivated,第二次使用 .Other,所以我最终打开了浏览器,但也浏览了 webview。
    • 如果我使用 open() 它使用 safari 浏览器打开 url。我想在我的应用程序中使用 wkwebview 打开我的网址。我如何实现它。任何人都可以帮忙。
    • 嗨@LeoDabus,我有一个URL,它只是更改了URL 的一个参数,但这种方法无法检测到它。这是那个 URL oporun.bubbleapps.io/version-test/appernaut。单击按钮时,它只更改一个参数
    • Leo,您对google.com 的使用可能具有误导性,因为这正是他用作其他 网站的示例。可以修改一下吗?
    • 我回答的最后一句话很清楚IMO
    【解决方案2】:

    这是用 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);
        }
    }
    

    【讨论】:

    • 不推荐使用没有其他参数的 openURL。使用:[[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@{} completionHandler:nil];
    【解决方案3】:

    对于 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)
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      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)
              }
      }
      

      【讨论】:

      • 把上面的代码放到你的 ViewController 类中,并在类声明中添加 WKUIDelegate:` class ViewController: UIViewController, WKUIDelegate {` 并在 viewDidLoad: mywebView.delegate = self 中添加
      【解决方案5】:

      我的 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)
              }
      
          }
      

      别忘了设置委托

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

      【讨论】:

        【解决方案6】:

        创建一个函数来决定在哪里加载 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)
            }
        }
        

        用法:

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

        【讨论】:

        • 抱歉,我花了这么长时间才回复你,但是当我点击我的 webview 中的外部链接时,你的代码不起作用,它仍然在 webview 中打开它。
        【解决方案7】:

        Swift 5 和 iOS >10

        不要使用UIApplication.shared.openURL(url!),它已被弃用。我们改用UIApplication.shared.open(url!)

         public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
                
                guard let url = navigationAction.request.url else{
                    decisionHandler(.allow)
                    return
                }
                
                let urlString = url.absoluteString.lowercased()
                if urlString.starts(with: "http://") || urlString.starts(with: "https://") {
                    decisionHandler(.cancel)
                    UIApplication.shared.open(url, options: [:])
                } else {
                    decisionHandler(.allow)
                }
                
            }
        

        【讨论】:

        • 由于某种原因,我的委托中没有调用此方法。我的WKNavigationDelegate 中的所有其他方法都被调用,但不是这个。有谁知道这可能是什么原因造成的?
        猜你喜欢
        • 2015-08-16
        • 1970-01-01
        • 1970-01-01
        • 2020-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多