For anyone having the same problem, here is how I was able to solve it eventually:
First of all I created a URL extension to test if the URL is reachable. This part is optional. I needed it so that users are not taken away from my app if indeed the URL leads nowhere:
extension URL {
func isReachable(completion: @escaping (Bool) -> ()) {
var request = URLRequest(url: self)
request.httpMethod = "HEAD"
URLSession.shared.dataTask(with: request) { _, response, _ in
completion((response as? HTTPURLResponse)?.statusCode == 200)
}.resume()
}
}
Then I created a Coordinator class to serve as the WKNavigationDelegate:
class Coordinator : NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else {
decisionHandler(.allow)
return
}
if url.absoluteString.contains("www.youtube.com"){ //In my case I needed to allow links with Youtube
decisionHandler(.allow)
} else {
url.isReachable { success in //To test if the URL is reachable
if success {
decisionHandler(.cancel)
DispatchQueue.main.async { //Needs to run on the main thread to prevent UI issues
UIApplication.shared.open(url)
}
} else {
decisionHandler(.allow)
}
}
}
}
}
I added the following line to my struct to make it aware of the Coordinator:
func makeCoordinator() -> Coordinator {
Coordinator()
}
Finally, I assign the coordinator as the view's navigation delegate
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.navigationDelegate = context.coordinator //Assign the coordinator as the view's navigation delegate
uiView.loadHTMLString(htmlContent, baseURL: nil)
}
And my links within the HTML String now open inside Safari instead of in my app.