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.