I am creating a user login page using MVVM architecture and I want to show an alert page if text field is empty or if wrong username / wrong password. So after login click and API call, if login failed, I want to show an alert, however I tried changing the state but still the alert does not show.
LoginView
struct LoginView: View {
@ObservedObject var user: User
@ObservedObject var viewModel = LoginViewModel()
@State var inputUser: String = ""
@State var inputPass: String = ""
@State private var showingAlert = true
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Group {
Text("Login")
CustomTextField(placeHolder: "Username", value: $viewModel.user)
CustomTextField(placeHolder: "Password", value: $viewModel.pass)
Button(action: {
self.viewModel.login { (isSuccess) in
if isSuccess {
self.user.tokenIsActive = true
} else {
// if login failed, show alert, but alert not showing
self.showingAlert = true
}
}
}) {
Text("Sign In")
}.buttonStyle(PrimaryButtonStyle())
.alert(isPresented: $showingAlert) {
Alert(title: Text("Error"), message: Text("Invalid username / password"), dismissButton: .default(Text("Got it!")))
}
}
}
}
}
}
LoginViewModel
class LoginViewModel: ObservableObject, LoginService {
var apiSession: APIService
@Published var user = ""
@Published var pass = ""
@Published var accessToken: String?
@Published var refreshToken: String?
@Published var showingAlert = true
var cancellables = Set<AnyCancellable>()
init(apiSession: APIService = APISession()) {
self.apiSession = apiSession
}
func login(_ completion: @escaping ((Bool)->Void)) {
let cancellable = self.loginUser(user: user, pass: pass)
.sink(receiveCompletion: { result in
switch result {
case .failure(let error):
print("Handle error: \(error)")
case .finished:
break
}
}) { (result) in
completion(true)
self.accessToken = result.accessToken
self.refreshToken = result.refreshToken
UserDefaults.standard.set(self.accessToken, forKey: "AccessToken")
UserDefaults.standard.set(self.refreshToken, forKey: "RefreshToken")
}
cancellables.insert(cancellable)
}
}
How do I show the alert? Thank you all in advance.