I am very new to Swift and I hit a problem where the UI does not change when the state variable changes.
My ContentView.swift:
struct ContentView: View {
@State private var loginModelInstance = LoginViewModel()
var body: some View {
if (!loginModelInstance.loginSuccessful)
{
LoginViewController(loginViewModel: $loginModelInstance)
}
else
{
FileUploaderView()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
My LoginViewController
struct LoginViewController: View {
@Binding var loginViewModel : LoginViewModel
var body: some View {
SignInWithAppleButton(.signIn,
onRequest: loginViewModel.configure,
onCompletion: loginViewModel.handle
)
.frame(height: 50)
.padding()
}
}
struct LoginViewController_Previews: PreviewProvider {
@State static var loginModelInstancePreview = LoginViewModel()
static var previews: some View {
LoginViewController(loginViewModel: $loginModelInstancePreview)
}
}
My FileUploader:
import SwiftUI
struct FileUploaderView: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
struct FileUploaderView_Previews: PreviewProvider {
static var previews: some View {
FileUploaderView()
}
}
My LoginViewModel
class LoginViewModel: ObservableObject
{
func configure(request: ASAuthorizationAppleIDRequest)
{
request.requestedScopes = [.fullName, .email]
// request.nonce = ""
}
func handle(authResult: Result<ASAuthorization, Error>) -> Void
{
switch authResult
{
case .success(let authorization):
self.loginSuccessful = true
self.objectWillChange.send()
print("Login for \(authorization) has been \(self.loginSuccessful)")
case .failure(let error):
self.loginSuccessful = false
print(error)
}
}
@Published var loginSuccessful: Bool = false
}
I have already looked into related questions: 1, 2
However, I wasn't able to get the view to change.
CodePudding user response:
You are using the property wrappers for your ViewModel the wrong way.
struct ContentView: View {
@State private var loginModelInstance = LoginViewModel()
should be
struct ContentView: View {
@StateObject var loginModelInstance = LoginViewModel()
and
struct LoginViewController: View {
@Binding var loginViewModel : LoginViewModel
should be
struct LoginViewController: View {
@ObservedObject var loginViewModel : LoginViewModel
I suggest to do some more research about fundamental SwiftUI concepts, for example here.