为什么我的视图在发布变量更新后不改变?



一旦用户登录到我的应用程序,我想将视图从SignInView更改为AppShellView。authData变量在UserViewModel中一旦从API接收到数据(通过print语句在UserViewModel中检查)就会完美地更新,但是这个更新没有反映在ContentView中,因为它总是显示SignInView。

为什么authData没有在ContentView中更新?

UserViewModel:

import SwiftUI
struct LoginRequestBody: Codable {
let email: String
let password: String
}
struct AuthData: Codable {
let token: String
let loggedInUser: User
}
class UserViewModel: ObservableObject {
// MARK: - PROPERTIES
@Published var authData: AuthData?

// MARK: - FUNCTIONS

func signIn(email: String, password: String) {
guard let url = URL(string: "http://localhost:4000/api/users/login") else {
return
}

let body = LoginRequestBody(email: email, password: password)

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONEncoder().encode(body)

URLSession.shared.dataTask(with: request) { [self] data, response, error in
guard let data = data, error == nil else {
return
}
guard let loginResponse = try? JSONDecoder().decode(AuthData.self, from: data) else {
return
}

self.authData = loginResponse

if let encoded = try? JSONEncoder().encode(self.authData) {
let defaults = UserDefaults.standard
defaults.set(encoded, forKey: "authData")
}
}.resume()
}
}

ContentView:

import SwiftUI
struct ContentView: View {
@ObservedObject var userViewModel = UserViewModel()

var body: some View {
if userViewModel.authData != nil {
AppShellView()
} else {
SignInView()
}
}
}

编辑:问题似乎如下:虽然代码成功地在UserViewModel中创建authData对象,但它不能在UserViewModel之外共享其更新状态(尽管被声明为@Published),无论在哪个其他结构或视图中我尝试使用它。

代码执行可能会在以下两个地方退出URLSession请求完成处理程序,而不更新'userViewModel.authData'。

guard let data = data, error == nil else {
return
}
guard let loginResponse = try? JSONDecoder().decode(AuthData.self, from: data) else {
return
}

要评估此假设,请添加打印或调试器断点。

此外,URLSession请求完成处理程序在非主线程上执行代码,因此

self.authData = loginResponse

应该被DispatchQueue.main.async封装。

错误可能存在于else子句中:

guard let data = data, error == nil else {
return
}

当它通过它时,由于您使用的url在http中,导致错误:

The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.

可以用Using HTTPS instead or add this domain to Exception Domains in your Info.plist来解

请注意,当您从后台线程更改UI时,您需要将self.authData = loginResponse部分包装在DispatchQueue.main.async {}上。

希望这有帮助,祝你好运!

相关内容

  • 没有找到相关文章

最新更新