I am using WebView for loading the html into view . I added the forward and back button to go back and forward with require code but the problem is when I enter the url and click more link , I do not see the back button or forward button is enable ..
Here is the content view ..
import SwiftUI
struct ContentView: View {
@State private var selection = 0
var body: some View {
TabView(selection: $selection) {
NavigationView {
WebListView().navigationBarTitle("Web View ", displayMode: .inline)
.toolbarBackground(Color.white,for: .navigationBar)
.toolbarBackground(.visible, for: .navigationBar)
.accentColor(.red)
.onAppear() {
UITabBar.appearance().barTintColor = .white
}
}.tabItem {
Image(systemName: "person.crop.circle")
Text("Web View")
}.tag(2)
}
}
}
Here is the code ListView ..
import SwiftUI
struct WebListView: View {
@StateObject var model = WebViewModel()
var body: some View {
WebContentView()
.font(.system(size: 30, weight: .bold, design: .rounded))
.toolbar {
ToolbarItemGroup(placement: .automatic) {
Button(action: {
model.goBack()
}, label: {
Image(systemName: "chevron.left")
})
.disabled(!model.canGoBack)
.font(.system(size: 20))
Button(action: {
model.goForward()
}, label: {
Image(systemName: "chevron.right")
})
.disabled(!model.canGoForward)
.font(.system(size: 20))
Spacer()
}
}
}
}
Code for UIViewRepresentable..
struct WebView: UIViewRepresentable {
typealias UIViewType = WKWebView
let webView: WKWebView
func makeUIView(context: Context) -> WKWebView {
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) { }
}
Here is the WebContent view code ..
import Combine
import WebKit
import SwiftUI
@MainActor
struct WebContentView: View {
@StateObject var model = WebViewModel()
var body: some View {
ZStack(alignment: .bottom) {
Color.blue
VStack(spacing: 0) {
HStack(spacing: 10) {
HStack {
TextField("Enter url",
text: $model.urlString)
.keyboardType(.URL)
.autocapitalization(.none)
.disableAutocorrection(true)
.padding(8)
.font(.system(size: 15))
Spacer()
}
.background(Color.white)
.cornerRadius(30)
Button("GO", action: {
model.loadUrl()
})
.foregroundColor(.white)
.padding(10)
.font(.system(size: 15))
.background(.blue)
}.padding(10)
ZStack {
WebView(webView: model.webView)
if model.isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
}
}
}
}
}
}
struct WebContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Here is the view Model code ..
@MainActor
class WebViewModel: ObservableObject {
let webView: WKWebView
private let navigationDelegate: WebViewNavigationDelegate
init() {
let configuration = WKWebViewConfiguration()
configuration.websiteDataStore = .nonPersistent()
webView = WKWebView(frame: .zero, configuration: configuration)
navigationDelegate = WebViewNavigationDelegate()
webView.navigationDelegate = navigationDelegate
setupBindings()
}
@Published var urlString: String = ""
@Published var canGoBack: Bool = false
@Published var canGoForward: Bool = false
@Published var isLoading: Bool = false
private func setupBindings() {
webView.publisher(for: \.canGoBack)
.assign(to: &$canGoBack)
webView.publisher(for: \.canGoForward)
.assign(to: &$canGoForward)
webView.publisher(for: \.isLoading)
.assign(to: &$isLoading)
}
func loadUrl() {
guard let url = URL(string: urlString) else {
return
}
webView.load(URLRequest(url: url))
}
func goForward() {
webView.goForward()
}
func goBack() {
webView.goBack()
}
}
here is code for delegate ..
import WebKit
class WebViewNavigationDelegate: NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// TODO
decisionHandler(.allow)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
// TODO
decisionHandler(.allow)
}
}
The problem is that you're creating a new WebViewModel
in WebContentView
Change
struct WebContentView: View {
@StateObject var model = WebViewModel()
//etc
}
to
struct WebContentView: View {
@EnvironmentObject var model: WebViewModel
//etc
}
Then update here…
struct WebListView: View {
@StateObject var model = WebViewModel()
var body: some View {
WebContentView()
.environmentObject(model) // add environmentObject