Search code examples
xcodeuiwebviewswiftuiwkwebviewswift5

goForward and goBack does not work in swiftui


I am trying to add the back and forward button in the swiftui but the buttons do not work. The URL comes from a firebase. I followed this question How to access goBack and goForward via UIViewRepresentable. If anyone help me, I am very thankful to you. Here is the source code

import SwiftUI
import WebKit
import Firebase

struct WebView: View {

    @State var websiteURL: String
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>


    var body: some View {
        ZStack{
            Color.init(red: 172/255, green: 198/255, blue: 224/255).edgesIgnoringSafeArea(.all)
            VStack{
                Button(action: {
                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Image("back").renderingMode(.original).frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 60, alignment: .leading).padding()
                }

                Webview(web: nil, req: URLRequest(url: URL(string: websiteURL)!))
                HStack{
                    Button(action: {
                        //go to back
                        Webview(web: nil, req: URLRequest(url: URL(string: websiteURL)!)).goBack()
                    }) {

                        Image(systemName: "arrow.left").foregroundColor(.black)
                    }
                    Spacer()
                    Button(action: {
                       // go forwared
                        Webview(web: nil, req: URLRequest(url: URL(string: websiteURL)!)).goForward()
                    }) {

                        Image(systemName: "arrow.right").foregroundColor(.black)
                    }
                }.padding([.leading,.trailing],20)
            }.navigationBarTitle("")
           .navigationBarHidden(true)
        }.onAppear{
            self.loadURL()

        }

    }
    func loadURL(){
           //For Admin
           let rootRef = Database.database().reference().child("Admin").child(websiteURL)

           rootRef.observeSingleEvent(of: .value, with: { (snapshot) in
             // Get user value
             let value = snapshot.value as? NSDictionary

               let getURL:String = value?["value"] as? String ?? ""
            self.websiteURL=getURL


             // ...
             }) { (error) in
               print(error.localizedDescription)
           }
       }
}

struct Webview : UIViewRepresentable {


  let request: URLRequest
  var webview: WKWebView?

  init(web: WKWebView?, req: URLRequest) {
      self.webview = WKWebView()
      self.request = req
  }

  func makeUIView(context: Context) -> WKWebView  {
      return webview!
  }

  func updateUIView(_ uiView: WKWebView, context: Context) {
      uiView.load(request)
  }

  func goBack(){
      webview?.goBack()
  }

  func goForward(){
      webview?.goForward()
  }
}

struct WebView_Previews: PreviewProvider {
    static var previews: some View {
        WebView(websiteURL: "")
    }
}

Solution

  • I stand by my comment, you create 3 different Webview. This is one way to make it work. Copy and paste this code and let me know if that works for you.

    import SwiftUI
    import WebKit
    import Firebase
    
    
    struct WebView: View {
    
    @State var websiteURL: String
    
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    let websiteView = Webview()
    
    var body: some View {
        ZStack{
            Color.init(red: 172/255, green: 198/255, blue: 224/255).edgesIgnoringSafeArea(.all)
            VStack{
                Button(action: {
                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Image("back").renderingMode(.original).frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 60, alignment: .leading).padding()
                }
                self.websiteView
                HStack{
                    Button(action: {
                        // go to back
                        self.websiteView.webview.goBack()
                    }) {
                        Image(systemName: "arrow.left").foregroundColor(.black)
                    }
                    Spacer()
                    Button(action: {
                        // go forwared
                        self.websiteView.webview.goForward()
                    }) {
                        Image(systemName: "arrow.right").foregroundColor(.black)
                    }
                }.padding([.leading,.trailing],20)
            }.navigationBarTitle("")
                .navigationBarHidden(true)
        }.onAppear{
            self.loadURL()
        }
    }
    
    func loadURL() {
           //For Admin
           let rootRef = Database.database().reference().child("Admin").child(websiteURL)
    
           rootRef.observeSingleEvent(of: .value, with: { (snapshot) in
             // Get user value
             let value = snapshot.value as? NSDictionary
    
            let getURL:String = value?["value"] as? String ?? ""
            self.websiteURL = getURL
    
            // new code <-----
            self.websiteView.loadRequest(request: URLRequest(url: URL(string: self.websiteURL)!))  
    
             // ...
             }) { (error) in
               print(error.localizedDescription)
           }
       }    
    }
    
    
    struct Webview : UIViewRepresentable {
    
    @State var request: URLRequest?
    
    let webview = WKWebView()
    
    func makeUIView(context: Context) -> WKWebView  {
        return webview
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        if request != nil { uiView.load(request!) }
    }
    
    func loadRequest(request: URLRequest) {
        self.request = request
        webview.load(request)
    }
    
    func goBack(){
        webview.goBack()
    }
    
    func goForward(){
        webview.goForward()
    }
    }