SwiftUI登录后LoginView不会消失

问题描述 投票:0回答:1

我使用的是 AppStateView() 来检查用户是否已登录。

struct AppStateView: View {

    @EnvironmentObject var appState: AppState

    var body: some View {
        if (self.appState.user != nil) {
            return AnyView(ContentView().environmentObject(appState))
        } else {
            return AnyView(LoginView().environmentObject(appState))
        }
    }
}

里面的 LoginView():

struct LoginView: View {

    @EnvironmentObject var appState: AppState

    @State private var username: String = ""
    @State private var password: String = ""

    var body: some View {
        NavigationView {
            VStack {
                TextField("Username", text: $username)
                SecureField("Password", text: $password)
                Button(action: {
                    self.appState.login(username: self.username, password: self.password) { user in
                        if user.accountId != 0 {
                            print("logged in")
                        } else {
                            print("not logged in")
                        }
                    }

                }) {
                    Text("LOGIN")
                }
                NavigationLink(destination: RegisterView()) {
                    Text("Sign Up")
                }
            }
        }
    }
}

有一个按钮调用appState.login函数。

struct User: Codable {
    let uid: Int
    let name: String
    let accountname: String
    let accountId: Int
    let startBalance: Double
}

class AppState: ObservableObject {

    @Published var user: User? = nil

    let apiURL: String = "http://localhost/api.php?"

    init() {
        if let user = UserDefaults.standard.object(forKey: "user") as? Data {
            if let loadedUser = try? JSONDecoder().decode(User.self, from: user) {
                self.user = loadedUser
            }
        }
    }

    func login(username: String, password: String, completion: @escaping (User) -> ()) {

        let urlstring = "\(apiURL)get_users&username=\(username)&password=\(password)"

        guard let url = URL(string: urlstring) else { return }

        URLSession.shared.dataTask(with: url) { (data, _, error) in

            guard let data = data, error == nil else {
                debugPrint("Fehler beim Laden von \(url)", String(describing: error))
                return
            }

            let user = try! JSONDecoder().decode(User.self, from: data)
            if let encoded = try? JSONEncoder().encode(user) {
                UserDefaults.standard.set(encoded, forKey: "user")
            }

            DispatchQueue.main.async {
                completion(user)
            }
        }.resume()

    }

    func logout() {
        self.user = nil
        UserDefaults.standard.removeObject(forKey: "user")
    }

}

根据我对可观察对象的理解,我认为,在按下登录按钮后,用户得到了更新,因此有了 LoginView() 视图在用户登录后会被重新加载。但它必须切换到 AppStateView(). 感觉有点怪怪的,要在里面添加第二个检查 LoginView() 以显示 LoginView()AppStateView() 因为我已经在 "父视图 "中做了。AppStateView().

ios authentication swiftui environment observableobject
1个回答
1
投票

下面是固定的部分代码

Button(action: {
    self.appState.login(username: self.username, password: self.password) { user in
        if user.accountId != 0 {
            print("logged in")
            self.appState.user = user       // << here !!
        } else {
            print("not logged in")
        }
    }

}) {
    Text("LOGIN")
}
© www.soinside.com 2019 - 2024. All rights reserved.