Skip to content

Instantly share code, notes, and snippets.

@getflourish
Last active November 24, 2023 19:45
Show Gist options
  • Save getflourish/6ebe51433dfedc238205c9af2d63874b to your computer and use it in GitHub Desktop.
Save getflourish/6ebe51433dfedc238205c9af2d63874b to your computer and use it in GitHub Desktop.
SwiftUI WebView
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
}
}
@getflourish
Copy link
Author

Signing & Capabilities

@mansidak
Copy link

mansidak commented Aug 6, 2022

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

@getflourish
Copy link
Author

@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
Copy link

mansidak commented Aug 7, 2022

@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 :/
Screen Shot 2022-08-07 at 9 27 08 AM

@mansidak
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment