I understand this question has been asked a lot and I think I have viewed every single post about this and I still cannot get this to work. I'm new to swift and I think that is inhibiting me from being able to adapt code snippets from other answers.
So here's my question:
I am using a WKWebView to view a website in my app. When I click on a link that opens a new tab nothing happens. I want that new tab to open in safari or at least in a new wkwebview. I've tried implementing this answer from: https://stackoverflow.com/a/27391215, and Open a WKWebview target="_blank" link in Safari and many other similar answers, but am making no progress. What do I need to do to make this work in swift 4?
Currently I just have this since I wasn't able to implement any of the other solutions I found successfully:
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
webView.load(navigationAction.request)
}
return nil
}
But it doesn't seem to do anything. If someone could help point me in the right direction I would really appreciate it.
I have pasted some sample code of a WKWebView project (load local html from folder) that requires links that have target=_blank
to open in a new browser window.
I have highlighted the 3 things you must have to get links to open correctly.
class ViewController extends WKUIDelegate
self.webView.uiDelegate = self
- Use
UIApplication.shared.open
instead of webView.load
Let me know it it works and if anyone can suggest improvements to the sample code below, that would help me too :)
Full sample code for Xcode 9.2, Swift 4 below.
Good Luck
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
@IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.webView.uiDelegate = self
let htmlPath = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")
let htmlUrl = URL(fileURLWithPath: htmlPath!)
let htmlDir = Bundle.main.url(forResource: "www", withExtension: nil)
webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlDir!)
}
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
//webView.load(navigationAction.request)
UIApplication.shared.open(navigationAction.request.url!, options: [:])
}
return nil
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override var prefersStatusBarHidden: Bool {
return true
}
}
Details
- Xcode 10.2 (10E125), Swift 5
Solution
extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// push new screen to the navigation controller when need to open url in another "tab"
if let url = navigationAction.request.url, navigationAction.targetFrame == nil {
let viewController = ViewController()
DispatchQueue.main.async { [weak self] in
self?.navigationController?.pushViewController(viewController, animated: true)
}
// .....
return viewController.webView
}
return nil
}
Full sample
Info.plist
add in your Info.plist transport security setting
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Code
import UIKit
import WebKit
class ViewController: UIViewController {
private lazy var url = URL(string: "https://google.com")!
private weak var webView: WKWebView?
func initWebView(configuration: WKWebViewConfiguration) {
if webView != nil { return }
let webView = WKWebView(frame: UIScreen.main.bounds, configuration: configuration)
webView.uiDelegate = self
view.addSubview(webView)
self.webView = webView
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if webView == nil { initWebView(configuration: WKWebViewConfiguration()) }
webView?.load(url: url)
}
}
extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// push new screen to the navigation controller when need to open url in another "tab"
if let url = navigationAction.request.url, navigationAction.targetFrame == nil {
let viewController = ViewController()
viewController.initWebView(configuration: configuration)
viewController.url = url
DispatchQueue.main.async { [weak self] in
self?.navigationController?.pushViewController(viewController, animated: true)
}
return viewController.webView
}
return nil
}
}
extension WKWebView {
func load(url: URL) { load(URLRequest(url: url)) }
}