Search code examples
swiftwebviewwhatsappmailtotel

How can I open external links in Swift webview?


I am totally new to Swift and I just need a webview app of my website. Everything seems fine except the external links such as "tel", "mailto", or "whatsapp". When I click them, nothing happens. I have searched many related titles and tried many things but the links are still not working. The last thing I tried is below. Can anyone help?


import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
    
    var webView: WKWebView!
    
    
    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let myURL = URL(string:"https://www.sepettte.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }

    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
      
      guard let failingUrlStr = (error as NSError).userInfo["NSErrorFailingURLStringKey"] 
      as? String  else { return }
      let failingUrl = URL(string: failingUrlStr)!

      switch failingUrl {
      
        case _ where failingUrlStr.hasPrefix("fb:"):
        if #available(iOS 10.0, *) {
           UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
           return
        }
          
        case _ where failingUrlStr.hasPrefix("whatsapp:"):
        if UIApplication.shared.canOpenURL(failingUrl) {
          UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
          return
        }

        case _ where failingUrlStr.hasPrefix("mailto:"):
        if UIApplication.shared.canOpenURL(failingUrl) {
          UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
          return
        }
          
        case _ where failingUrlStr.hasPrefix("tel:"):
        if UIApplication.shared.canOpenURL(failingUrl) {
          UIApplication.shared.open(failingUrl, options: [:], completionHandler: nil)
          return
        }

      default: break
      }
    }
}


Solution

  • Try intercepting requests on WKWebView implementing decidePolicyFor navigationAction :

    class ViewController: UIViewController, WKNavigationDelegate {
        
        @IBOutlet weak var webView: WKWebView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            webView.uiDelegate = self
            webView.navigationDelegate = self
    
            webView.allowsBackForwardNavigationGestures = true
    
            let myURL = URL(string:"https://www.sepettte.com")
            let myRequest = URLRequest(url: myURL!)
            webView.load(myRequest)
        }
        
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
            
            guard let redirectURL = (navigationAction.request.url) else {
                decisionHandler(.cancel)
                return
            }
            
            if (redirectURL.absoluteString.contains("tel:") ) {
                UIApplication.shared.open(redirectURL, options: [:], completionHandler: nil)
            }
            
            if (redirectURL.absoluteString.contains("whatsapp") ) {
                UIApplication.shared.open(redirectURL, options: [:], completionHandler: nil)
            }
            
            decisionHandler(.allow)
        }
    }
    
    extension ViewController: WKUIDelegate {
    
        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
        }
    }
    

    Output:

    enter image description here