我正在尝试构建一个Singleton ApiManager类,它可以为我构建和发送所有API请求,并将响应数据发送到等待请求的对象。在SwiftUI中,当我看到,假设用户成功登录,我想把视图切换到一个 Jmeter 板,问题是我使用ObservableObject来发布"isLoggedIn"布尔值,并且我在后台线程上发出所有的后端请求。我收到此错误
- [SwiftUI]不允许从后台线程发布更改;确保在模型更新时从主线程发布值(通过receive(on:)等操作符)。*
下面是执行API请求的方法
func performRequest(with request: some AbstractRequest) {
var link = host + request.endpoint
appendParameters(to: &link, with: request.params)
guard let url = URL(string: link) else {
print("Failed to generate url from \(link)")
return
}
let task = URLSession.shared.dataTask(with: url){ data, response, error in
guard let data = data, error == nil else{
print("\(error?.localizedDescription ?? "")")
return
}
request.completion(data: data)
}
task.resume()
}
下面是一个示例完成处理程序(如果您能告诉我为什么会收到此警告,则会加分
- 从"[LoginResponse]"到"[LoginResponse]"的条件强制转换始终成功**
在石膏线上,但如果我取下石膏,它会抱怨。)
func completion(data: Data)
{
do{
guard let response = try JSONDecoder().decode([LoginResponse].self, from: data) as? [LoginResponse] else { return }
delegate.responseReceived(response: response)
}catch let error{
print("\(error.localizedDescription)")
}
}
下面是我的LoginManager的外观
class LoginManager: ObservableObject, ApiRequestDelegate{
static var shared = LoginManager()
var token = ""
@Published var isLoggedIn: Bool = false
func responseReceived(response: Any) {
guard let response = response as? LoginResponse, response.token != -1 else { return }
token = String(response.token)
isLoggedIn = true
}
}
最后是我的内容视图
struct ContentView: View {
@ObservedObject var loginManager = LoginManager.shared
var body: some View {
if !loginManager.isLoggedIn {
LoginView()
}else {
OpenLinkButton().ignoresSafeArea()
}
}
}
1条答案
按热度按时间xxhby3vn1#
URLSession.shared.dataTask
中的完成处理程序是在后台线程上调用的,因此后面的所有操作都在后台线程上执行。最简单的解决方案是将UI更改分派给主线程。例如:
另一种解决方案是用
@MainActor
属性来修饰与UI交互的函数,例如: