Search code examples
swiftswiftuiasync-awaitalertviewbuilder

Showing alert function when the button is click with Async and Await function


I am have the username and password text filed with button . I am expecting when username or password is not correct that time I want to show alert view and message saying that incorrect username or password when user click the signing button . I am handing the concurrency with async and await . But the issue is the alert function is not getting called ..

Here is the my code ..

import SwiftUI

struct LoginView: View {
    @State private var username = ""
    @State private var password = ""
    @EnvironmentObject var viewModel: AuthViewModel
    
    var body: some View {
        
        NavigationStack {
            
            VStack {
                // Login Image
                Image("signin")
                    .resizable()
                    .scaledToFill()
                    .frame(width: 100, height: 120)
                    .padding(.vertical, 32)
                
                // form filed
                VStack(spacing: 24) {
                    InputView(text: $username, title: "username", placeholder: "[email protected]")
                        .autocapitalization(.none)
                    InputView(text: $password, title: "password", placeholder: "enter your password", isSecureField: true)
                    
                }
                .padding(.horizontal)
                .padding(.top, 15)
                
                // creating sign in button
                
                Button {
                    
                    Task {
                        try await viewModel.signIn(withEmail: username, password: password)
                    }
                    
                } label: {
                    HStack {
                        Text("Sign In")
                            .fontWeight(.semibold)
                        Image(systemName: "arrow.right")
                    }
                    .foregroundColor(.white)
                    .frame(width: UIScreen.main.bounds.width - 32 , height: 40)
                    
                }
                .background(Color(.systemBlue))
                .disabled(!formValid)
                .opacity(formValid ? 1.0: 0.5)
                .cornerRadius(10)
                .padding(.top ,24)
                
                Spacer()
                
                // sign up button
                
                NavigationLink {
                    RegistrationView()
                    // Hiding the navigation back button hidden .
                        .navigationBarBackButtonHidden(true)
                } label: {
                    HStack(spacing: 3) {
                        Text("Dont have an account?")
                        Text("Sign up")
                            .fontWeight(.bold)
                    }
                    .font(.system(size: 14))
                }
            }
            .alert(isPresented: $viewModel.isErrorOccured) {
                Alert(title: Text("Incorrect Username or password"), message: Text(viewModel.customError?.localizedDescription ?? ""),dismissButton: .default(Text("Okay")))
            }
        }
    }
}

Solution

  • BTW there is no code in your snippet that shows where you change value of showingAlert to true and curly braces after the Button expects action code not a view , the correct way is to attach .alert modifier to closing of VStack

    VStack {
       // Login Image
       Image("signin")
       .....
       .....
       .....
    }
    .alert(isPresented: $viewModel.isErrorOccured) {
       Alert(title: Text("Incorrect Username or password"), message: Text(viewModel.customError?.localizedDescription ?? ""),dismissButton: .default(Text("Okay")))
    }
    

    And replace

    Task {
        if showingAlert == false {
          try await viewModel.signIn(withEmail: username, password: password)
       } else {
           alertView() // this function not getting called.
       }
     }
    

    with

    Task {
          try await viewModel.signIn(withEmail: username, password: password)
    }