You have a web view in your application but would like any links clicked to open in Safari. Here’s the solution.
For WKWebView, first ensure your view controller conforms to WKNavigationDelegate
class MyViewController: UIViewController, WKNavigationDelegate {
// TODO: code here
}I like to put it in an extension to keep things neat:
extension MyViewController: WKNavigationDelegate {
// TODO: code here
}Next you need to implement the decidePolicyFor navigationAction function:
extension MyViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.navigationType == .linkActivated {
if let url = navigationAction.request.url,
UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
decisionHandler(.cancel)
} else {
// Open in web view
decisionHandler(.allow)
}
} else {
// other navigation type, such as reload, back or forward buttons
decisionHandler(.allow)
}
}
}Lastly, you’ll need to set the navigation delegate in viewDidLoad() or in the storyboard:
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
}For UIWebView (which is a deprecated by the way), use the below code:
First, you must ensure that your view controller conforms to UIWebViewDelegate.
class MyViewController: UIViewController, UIWebViewDelegate {
// TODO: code here
}You could also do this in an extension to keep things neat:
extension MyViewController: UIWebViewDelegate {
// TODO: code here
}Then you need to implement the webViewShouldStartLoadingWithRequest:navigationType: function:
extension MyViewController: UIWebViewDelegate {
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
switch navigationType {
case .linkClicked:
guard let url = request.url else { return true }
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
return false
default:
// TODO: handle other navigation types such reload, back or forward...
return true
}
}
}Lastly, you’ll need to set the delegate of your webview in your viewDidLoad() or in your storyboard/XIB.
override func viewDidLoad() {
super.viewDidLoad()
webview.delegate = self
}If you only want to open certain domains in Safari, perform a check on the URL string in the delegate method.
For example, if we’re using a WKWebView and we only want to open google.com links in Safari, we would add this check:
if let host = url.host, host.hasPrefix("www.google.com") {
// TODO: redirect to browser
}Full code example for WKWebView:
extension MyViewController: WKNavigationDelegate {
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)
decisionHandler(.cancel)
} else {
// Open in web view
decisionHandler(.allow)
}
} else {
// other navigation type, such as reload, back or forward buttons
decisionHandler(.allow)
}
}
}We can perform a URL host check for the UIWebView:
if let host = url.host, host.hasPrefix("www.google.com") {
// TODO: Open url in Safari
}Full code example:
extension MyViewController: UIWebViewDelegate {
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
switch navigationType {
case .linkClicked:
guard let url = request.url, let host = url.host, host.hasPrefix("www.google.com") else { return true }
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
return false
default:
// TODO: handle other navigation types such reload, back or forward...
return true
}
}
}
The Complete iOS App Development Bootcamp
Disclosure: This website may contain affiliate links, meaning when you click the links and make a purchase, we receive a commission.