SwiftUI:Observable 对象不会在 View 中更新?
SwiftUI: Observable Object does not update in View?
我在这里苦苦挣扎了好几天:我有一个异步函数,它从 LoadingView 中的计时器调用 onRecieve。它从 class ViewModel 调用 getData 函数。使用 HTTP Get Request 获取数据并进行比较:如果获取的 ID = 我应用程序中的 transactionID,并且获取的 Status =“成功”,则支付成功。
这在我的可观察 class 中切换。看看:
//View Model
@MainActor class ViewModel: ObservableObject {
@Published var fetchedData = FetchedData()
@Published var successfullPayment: Bool = false
@Published var information: String = "Versuch's weiter!"
// Function to fetch Data from the Databank
func getData() {
guard let url = URL(string: getUrl) else {return}
URLSession.shared.dataTask(with: url) { (data, res, err) in
do{
if let data = data {
let result = try JSONDecoder().decode(FetchedData.self, from: data)
DispatchQueue.main.async {
self.fetchedData = result
if self.fetchedData.id == transactionId && self.fetchedData.statuscode == "Success" {
self.successfullPayment = true
print("Payment was successful")
} else {print("Pending ...")}
}
} else {
print("No data")
}
} catch (let error) {
print(error.localizedDescription)
}
}.resume()
}
}
这是我观察到的 LoadingView:
结构加载视图:视图{
//Timer
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State private var counter = 0
@State var paymentCancelled = false
@ObservedObject var observable: ViewModel
var body: some View {
ZStack {
Image("money")
.resizable()
.aspectRatio(contentMode: .fit)
VStack {
if self.observable.successfullPayment == true{
Text("Thanks you" as String)
.font(.largeTitle)
.fontWeight(.black)
.multilineTextAlignment(.center)
.padding(.top, 100)
} else {
Text("Paying ..." as String)
.font(.largeTitle)
.fontWeight(.black)
.multilineTextAlignment(.center)
.padding(.top, 100)
}
PushView(destination: CancelledView(), isActive: $paymentCancelled) {
Spacer()
}
Button {
paymentCancelled.toggle()
print("payment cancelled!")
} label: {
Label("Abbrechen", systemImage: "nosign")
.padding(.horizontal, 40)
.padding(.vertical, 10.0)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(10)
.font(Font.body.weight(.medium))
}
.padding(.bottom, 50)
}
.navigationBarTitle("")
.navigationBarHidden(true)
}
.onReceive(timer) { time in
if counter == 90 {
timer.upstream.connect().cancel()
print("Timer cancelled")
} else {
ViewModel().getData()
}
counter += 1
}
}
}
但是发布的 var successfullPayment 没有更新视图。我在这里错过了什么?跟async函数有关系吗?
我将只关注对 getData()
的调用。您的视图正在调用以下命令:
ViewModel().getData()
这意味着您正在视图模型的 new 实例上调用该函数。因此,变量 fetchedData
和 successfullPayment
将在一个不是视图中使用的实例上更新。
第一步是使用您在视图中拥有的相同实例:
observable.getData()
确保调用 LoadingView
的视图具有 ViewModel
类型的 @StateObject
并且您正在正确传递它。
我在这里苦苦挣扎了好几天:我有一个异步函数,它从 LoadingView 中的计时器调用 onRecieve。它从 class ViewModel 调用 getData 函数。使用 HTTP Get Request 获取数据并进行比较:如果获取的 ID = 我应用程序中的 transactionID,并且获取的 Status =“成功”,则支付成功。
这在我的可观察 class 中切换。看看:
//View Model
@MainActor class ViewModel: ObservableObject {
@Published var fetchedData = FetchedData()
@Published var successfullPayment: Bool = false
@Published var information: String = "Versuch's weiter!"
// Function to fetch Data from the Databank
func getData() {
guard let url = URL(string: getUrl) else {return}
URLSession.shared.dataTask(with: url) { (data, res, err) in
do{
if let data = data {
let result = try JSONDecoder().decode(FetchedData.self, from: data)
DispatchQueue.main.async {
self.fetchedData = result
if self.fetchedData.id == transactionId && self.fetchedData.statuscode == "Success" {
self.successfullPayment = true
print("Payment was successful")
} else {print("Pending ...")}
}
} else {
print("No data")
}
} catch (let error) {
print(error.localizedDescription)
}
}.resume()
}
}
这是我观察到的 LoadingView:
结构加载视图:视图{
//Timer
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State private var counter = 0
@State var paymentCancelled = false
@ObservedObject var observable: ViewModel
var body: some View {
ZStack {
Image("money")
.resizable()
.aspectRatio(contentMode: .fit)
VStack {
if self.observable.successfullPayment == true{
Text("Thanks you" as String)
.font(.largeTitle)
.fontWeight(.black)
.multilineTextAlignment(.center)
.padding(.top, 100)
} else {
Text("Paying ..." as String)
.font(.largeTitle)
.fontWeight(.black)
.multilineTextAlignment(.center)
.padding(.top, 100)
}
PushView(destination: CancelledView(), isActive: $paymentCancelled) {
Spacer()
}
Button {
paymentCancelled.toggle()
print("payment cancelled!")
} label: {
Label("Abbrechen", systemImage: "nosign")
.padding(.horizontal, 40)
.padding(.vertical, 10.0)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(10)
.font(Font.body.weight(.medium))
}
.padding(.bottom, 50)
}
.navigationBarTitle("")
.navigationBarHidden(true)
}
.onReceive(timer) { time in
if counter == 90 {
timer.upstream.connect().cancel()
print("Timer cancelled")
} else {
ViewModel().getData()
}
counter += 1
}
}
}
但是发布的 var successfullPayment 没有更新视图。我在这里错过了什么?跟async函数有关系吗?
我将只关注对 getData()
的调用。您的视图正在调用以下命令:
ViewModel().getData()
这意味着您正在视图模型的 new 实例上调用该函数。因此,变量 fetchedData
和 successfullPayment
将在一个不是视图中使用的实例上更新。
第一步是使用您在视图中拥有的相同实例:
observable.getData()
确保调用 LoadingView
的视图具有 ViewModel
类型的 @StateObject
并且您正在正确传递它。