How to go back to previous screen after getting response from API call in swiftui?

Viewed 316

I am new in swift ui, I try to go back to previous screen after getting response from API call.

In my scenario, I have a button to call an API. This is my button,

import SwiftUI

struct RegisterCashierView: View {
    @ObservedObject var registerCashierController = RegisterCashierController()
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    var body: some View {
      Button(action: {
        if(self.registerCashierController.isActive){
          self.presentationMode.wrappedValue.dismiss()
        }
        self.registerCashierController.submitRegisterCashier(email: self.email, full_name: self.full_name, username: self.username, password: self.password)
      }) {
      HStack {
        Text("Submit")
            .fontWeight(.semibold)
            .font(.title)
        Image(systemName: "arrow.right.circle")
            .font(.title)
      }
      .frame(minWidth: 0, maxWidth: .infinity)
      .padding()
    }
}

As we can see I have an isActive, when isActive is true, it will execute this

self.presentationMode.wrappedValue.dismiss()

I set my isActive to true variable after getting an response from API. But it is not work. Any one knows how to fix this?

class RegisterCashierController: ObservableObject {
    @Published var isActive = false
    @Published var isLoading = false
    @State private var adminToken = UserDefaults.standard.string(forKey: "adminToken")
    let url = BaseUrl().setUrl(subUrl: "auth/user/register")
    var didChange = PassthroughSubject<RegisterCashierController, Never>()
    
    func submitRegisterCashier(email: String, full_name: String, username: String, password: String){
        let body : [String : String] = ["email": email, "full_name": full_name, "username": username, "password": password]
        guard let finalBody = try? JSONEncoder().encode(body) else {
            return
        }
        print("URL \(self.url)")
        var request = URLRequest(url: self.url)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("Bearer \(adminToken ?? "")", forHTTPHeaderField: "Authorization")
        request.httpMethod = "POST"
        request.httpBody = finalBody
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            guard let data = data, error == nil else {
                print("No data response")
                return
            }
            do {
                let decoder = JSONDecoder()
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
                decoder.dateDecodingStrategy = .formatted(dateFormatter)
                let response = try decoder.decode(RegisterCashierResponse.self, from: data)
                DispatchQueue.main.async {
                    self.isActive = true
                    self.isLoading = false
                }
                print("Response from register cashier \(response)")
            } catch let error {
                print("Error from register cashier \(error)")
            }
        }.resume()
    }
}

1 Answers

It works differently - you have to observe isActive, for example in onChange:

var body: some View {
  Button(action: {
    self.registerCashierController.submitRegisterCashier(email: self.email, full_name: self.full_name, username: self.username, password: self.password)
  }) {
  HStack {
    Text("Submit")
        .fontWeight(.semibold)
        .font(.title)
    Image(systemName: "arrow.right.circle")
        .font(.title)
  }
  .frame(minWidth: 0, maxWidth: .infinity)
  .padding()
  .onReceive(registerCashierController.$isActive) { active in // SwiftUI 1.0+
 // .onChange(of: registerCashierController.isActive) { active in // SwiftUI 2.0
    if active {
      self.presentationMode.wrappedValue.dismiss()
    }
  }
}
Related