Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Changing views via conditional statements inside of async commands in SwiftUI IOS15

I’m trying to have a user go onto the ContentView and login, now this will either log them in or return to the ContentView (Will create errors and things later for failed login). At the moment I can login and I pull the required data from my API, it will then run a conditional of true if they’re successful or false if they are not. Inside the conditional is a print statement of Success if true or Unsuccessful if false. This all runs fine but when I put a statement in to change views it doesn’t change the view. I’m sure its got to do with async/await but I’m pretty new to SwiftUI. I have included the ContentView code for reference. Its not a super complicated process but I can’t seem to find much information about changing view in this manner. It might be the wrong approach, so any advice would be awesome.

import SwiftUI

struct ContentView: View {
    @State var username : String = ""
    @State var password : String = ""
    @State var loggedIn : Bool = false
    @State var network = NetworkCall()
    var body: some View {
        ZStack {
            Color(red: 0.4627, green: 0.8392, blue: 1.0).ignoresSafeArea()
            VStack {
                Text("Login")
                    .padding()
                TextField("Username", text: $username)
                    .padding()
                SecureField("Password", text: $password)
                    .padding()
                
                Button(action: {
                    Task {
                        do{
                            try await loggedIn = network.LoginFunction(userName: username, passWord: password)
                            if(loggedIn){
                                print("Login Successful")
                                Dashboard()
                            }
                            else {
                                print("Login Unsuccessful")
                                ContentView()
                            }
                        }catch{
                            print("error", error)
                        }                        
                    }
                }) {
                    Text("Sign in")
                        .padding()
                        .frame(minWidth: 100, maxWidth: 300, minHeight: 44)
                        .foregroundColor(Color.white)
                        .cornerRadius(30)
                        .background(Color.blue)
                        .cornerRadius(20)
                }
            }
        }
    }
}

The Network Caller

import Foundation
class NetworkCall {
    func LoginFunction(userName: String, passWord: String) async throws -> Bool {
        
        let parameters = "{\r\n    \"uEmail\" : \"" + userName + " \",\r\n    \"uPassword\" : \"" + passWord + "\" \r\n}"
        let postData = parameters.data(using: .utf8)
        
        var request = URLRequest(url: URL(string: "https://..........................")!,timeoutInterval: Double.infinity)
        
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = postData

        let (data, response) = try await URLSession.shared.data(for: request)
        guard (response as? HTTPURLResponse)?.statusCode == 200 else { fatalError("Error while fetching data") }
        let decodedUser = try JSONDecoder().decode(UserClass.self, from: data)
        print(decodedUser.userinfo.user_guid)
        
        if(decodedUser.status){
            return true
        }
        else{
            return false
        }
    }

}


MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

SwiftUI renders your user interface in response to changes in state. So instead of trying to render Dashboard or ContentView within your Task, instead you need to set some form of state higher up that determines which view to show to the user.

For example, if you had a @State variable recording your logged in status, your code would start to look like

struct ContentView: View {
  @State var loggedIn = false

  var body: some View {
    if loggedIn {
      Dashboard()
    } else {
      // login form
      Button {
        Task {
          let logInStatus = try await network.LoginFunction(userName: username, passWord: password)
          self.loggedIn = logInStatus
        }
      }
    }
  }
}

When your async tasks changes the ContentView’s state, SwiftUI’s rendering subsystem will pick up that loggedIn has changed, and re-render body so that the login form is replaced by a call to Dashboard().

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading