The code has been tested on July 7, 2021 on macOS 11.4.
Based on https://gist.github.com/swiftui-lab/a873bf413770db6fd1a525fa424ce8cd by swiftui-lab.
Usage: https://florianschulz.info/portfolio/writing/wrapping-websites-in-webviews-using-swiftui
The code has been tested on July 7, 2021 on macOS 11.4.
Based on https://gist.github.com/swiftui-lab/a873bf413770db6fd1a525fa424ce8cd by swiftui-lab.
Usage: https://florianschulz.info/portfolio/writing/wrapping-websites-in-webviews-using-swiftui
import SwiftUI | |
@available(OSX 11.0, *) | |
struct ContentView: View { | |
private var url: URL? = URL(string: "https://apple.com") | |
init() { | |
print("Hello World") | |
} | |
var body: some View { | |
WebView(data: WebViewData(url: self.url!)) | |
} | |
} | |
import SwiftUI | |
import WebKit | |
import Combine | |
class WebViewData: ObservableObject { | |
@Published var loading: Bool = false | |
@Published var url: URL?; | |
init (url: URL) { | |
self.url = url | |
} | |
} | |
@available(OSX 11.0, *) | |
struct WebView: NSViewRepresentable { | |
@ObservedObject var data: WebViewData | |
func makeNSView(context: Context) -> WKWebView { | |
return context.coordinator.webView | |
} | |
func updateNSView(_ nsView: WKWebView, context: Context) { | |
guard context.coordinator.loadedUrl != data.url else { return } | |
context.coordinator.loadedUrl = data.url | |
if let url = data.url { | |
DispatchQueue.main.async { | |
let request = URLRequest(url: url) | |
nsView.load(request) | |
} | |
} | |
context.coordinator.data.url = data.url | |
} | |
func makeCoordinator() -> WebViewCoordinator { | |
return WebViewCoordinator(data: data) | |
} | |
} | |
@available(OSX 11.0, *) | |
class WebViewCoordinator: NSObject, WKNavigationDelegate { | |
@ObservedObject var data: WebViewData | |
var webView: WKWebView = WKWebView() | |
var loadedUrl: URL? = nil | |
init(data: WebViewData) { | |
self.data = data | |
super.init() | |
webView.navigationDelegate = self | |
} | |
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | |
DispatchQueue.main.async { | |
self.data.loading = false | |
} | |
} | |
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { | |
DispatchQueue.main.async { self.data.loading = true } | |
} | |
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { | |
showError(title: "Navigation Error", message: error.localizedDescription) | |
DispatchQueue.main.async { self.data.loading = false } | |
} | |
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { | |
showError(title: "Loading Error", message: error.localizedDescription) | |
DispatchQueue.main.async { self.data.loading = false } | |
} | |
func showError(title: String, message: String) { | |
#if os(macOS) | |
let alert: NSAlert = NSAlert() | |
alert.messageText = title | |
alert.informativeText = message | |
alert.alertStyle = .warning | |
alert.runModal() | |
#else | |
print("\(title): \(message)") | |
#endif | |
} | |
} |
Hey there! This was a lovely tutorial. Would you know how to allow downloads through WKWEbView? So I tried using Download Delegate to handle that but I get an error saying "Loading Error (Frame load interrupted) ". This is what I tried:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { if navigationAction.request.url?.pathExtension == "doc" { decisionHandler(.download) } else { decisionHandler(.allow) } }
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { if navigationResponse.response.mimeType == "application/msword" { decisionHandler(.download) } else { decisionHandler(.allow) } }
EDIT: Edited the syntax to look a little better @getflourish
@mansidak I don’t know the answer but it looks like you are on the right path. Any luck with these answers here? https://stackoverflow.com/questions/59083340/how-to-download-files-in-wkwebview
@mansidak I don’t know the answer but it looks like you are on the right path. Any luck with these answers here? https://stackoverflow.com/questions/59083340/how-to-download-files-in-wkwebview
Hi, @getflourish! Thanks for the reply. I've been working with that answer since yesterday actually. I tried it out but I'm not sure how to approach the second part of that answer. The 2.2 part to be specific. I've never used WKDownloadDelegate before so I'm not sure what to add into the url path and the part where it says in a comment "// your WKDownloadDelegate
".
I tried the following because I know I'll have to use NSSavePanel at some point but I'm pretty sure this isn't correct :/
Nevermind I was able to of a a javascript workaround! Thanks for the tutorial regardless :) I have to point out one thing though: idk if it's how we setup webview in your tutorial or just the nature of WKWebView in general, but regular keyboard shortcuts like 'cmd+A' to select text don't work inside the webview. I'm looking into that right now but if you have any info, let me know. You can easily reproduce the error on your side by just running something in webview and trying to select text inside of that.
Signing & Capabilities