SwiftUI:可观察对象在视图中没有更新?
我现在在这里苦苦挣扎了好几天:我有一个 async
函数,它从 LoadingView
中的计时器调用 onRecieve
。它从 ViewModel
类调用 getData 函数。通过 HTTP Get 请求获取数据并进行比较:如果获取的 ID = 我的应用程序中的 transactionID,并且获取的 Status =“成功”,则支付成功。
这是在我的可观察类中切换的。看一下:
//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
:
struct LoadingView: View {
//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 函数有关吗?
I am struggling here for days now: I have a async
function that get's called onRecieve
from a timer in a LoadingView
. It calls the getData function from the class ViewModel
. Data gets fetched with an HTTP Get Request and compared: if the fetched ID = to the transactionID in my app and the fetched Status = "Success", then the payment is successful.
This is toggled in my observable class. Have a look:
//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()
}
}
And this is my observing LoadingView
:
struct LoadingView: View {
//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
}
}
}
But the published var successfullPayment
doesn't update the View. What am I missing here? Has it to do with the async function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我将只关注对
getData()
的调用。您的视图正在调用以下命令:这意味着您正在视图模型的新实例上调用该函数。因此,变量
fetchedData
和successfullPayment
将在视图中未使用的实例上更新。第一步是使用视图中的相同实例:
确保调用
LoadingView
的视图具有ViewModel
类型的@StateObject
code> 并且您正确传递了它。I will focus only on the call to
getData()
. Your view is calling the following command:This means that you are calling the function on a new instance of the view model. So, the variables
fetchedData
andsuccessfullPayment
will be updated on an instance which is not the one being used in the view.The first step would be to use the same instance that you have in your view:
Be sure that the view calling
LoadingView
has a@StateObject
of typeViewModel
and that you are passing it correctly.