SwiftUI WKWebView detect url changing
You can simply create a ObservableObject model class of webview with the name "WebViewModel" like
class WebViewModel: ObservableObject { @Published var link: String @Published var didFinishLoading: Bool = false init (link: String) { self.link = link }}
and also import
import WebKitimport Combine
and then copy this code snippets
struct SwiftUIWebView: UIViewRepresentable { @ObservedObject var viewModel: WebViewModel let webView = WKWebView() func makeUIView(context: UIViewRepresentableContext<SwiftUIWebView>) -> WKWebView { self.webView.navigationDelegate = context.coordinator if let url = URL(string: viewModel.link) { self.webView.load(URLRequest(url: url)) } return self.webView } func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<SwiftUIWebView>) { return } class Coordinator: NSObject, WKNavigationDelegate { private var viewModel: WebViewModel init(_ viewModel: WebViewModel) { self.viewModel = viewModel } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { //print("WebView: navigation finished") self.viewModel.didFinishLoading = true } } func makeCoordinator() -> SwiftUIWebView.Coordinator { Coordinator(viewModel) }}struct SwiftUIWebView_Previews: PreviewProvider { static var previews: some View { SwiftUIWebView(viewModel: WebViewModel(link: "https://google.com")) //WebView(request: URLRequest(url: URL(string: "https://www.apple.com")!)) }}
and in you view
struct AnyView: View { @ObservedObject var model = WebViewModel(link: "https://www.wikipedia.org/") var body: some View { NavigationView { SwiftUIWebView(viewModel: model) if model.didFinishLoading { //do your stuff } } }}
so in this way you can get the others delegates response.
you use this to delegates of WKNavigationProtocol to perform(e.g to allow or cancel URL Loading) your action
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { if let host = navigationAction.request.url?.host { if host.contains("facebook.com") { decisionHandler(.cancel) return } } decisionHandler(.allow)}
Use the following delegate function of WKWebView
:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { // Suppose you don't want your user to go a restricted site if let host = navigationAction.request.url?.host { if host == "restricted.com" { decisionHandler(.cancel) return } } decisionHandler(.allow)}
You can read this article from Medium
which shows a better way of intercepting every network
call or Url
changing and obtaining upcoming Url
related data
. It also shows how to implement WebView
in SwiftUI
, interfacing with JavaScript
functions and loading a local .html
file from iOS project