Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
807 views
in Technique[技术] by (71.8m points)

swift - SwiftUI MVVM how to set callback from ViewModel function to View

I am setting up a login page logic with MVVM and I could not figure out how to modify the user login state after calling the function from ViewModel.

LoginView

struct LoginView: View {
    @ObservedObject var user: User
    @ObservedObject var viewModel = LoginViewModel()
    @State var inputUser: String = ""
    @State var inputPass: String = ""
    
    var body: some View {
        ScrollView {
            VStack(alignment: .leading) {
                Group {
                    Text("Login")
                    CustomTextField(placeHolder: "Username", value: $viewModel.user, secure: false)
                    CustomTextField(placeHolder: "Password", value: $viewModel.pass, secure: true)
                    Button(action: {
                        self.viewModel.login()
                        // After this login function completes and if return result success
                        // How do I pass data / callback after login?
                        // How to check if login success then set token or login failed
                        self.user.tokenIsActive = true
                    }) {
                        Text("Sign In")
                    }
                }
            }
        }
    }
}

LoginViewModel

class LoginViewModel: ObservableObject, LoginService {
    var apiSession: APIService
    
    @Published var user = ""
    @Published var pass = ""
    
    @Published var accessToken: String?
    
    var cancellables = Set<AnyCancellable>()
    
    init(apiSession: APIService = APISession()) {
        self.apiSession = apiSession
    }
    
    func login() {
        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
                self.accessToken = result.accessToken
                UserDefaults.standard.set(self.accessToken, forKey: "accessToken")
        }
        cancellables.insert(cancellable)
    }
}

User

So I store the user session in User class

class User: ObservableObject {
    @Published var tokenIsActive = false;
}

How do I pass data from the login function in viewmodel and check if login is success and set user token? Thank you in advance.

question from:https://stackoverflow.com/questions/65879229/swiftui-mvvm-how-to-set-callback-from-viewmodel-function-to-view

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use completion block and update your status.

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
            UserDefaults.standard.set(self.accessToken, forKey: "accessToken")
    }
    cancellables.insert(cancellable)
}

Use :

self.viewModel.login { (isSuccess) in
    if isSuccess {
        self.user.tokenIsActive = true
    }
}


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...