Home > OS >  SwiftUI view does not change after State variable changes
SwiftUI view does not change after State variable changes

Time:10-07

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.

  • Related