[英]SwiftUI - onChange not getting called
Adding the code first to help better understand the problem.首先添加代码以帮助更好地理解问题。
struct MainSetupView: View {
@StateObject var viewModel: MainViewModel
var body: some View {
VStack {
switch viewModel.state {
case .idle:
Color.clear.onAppear(perform: { viewModel.prepare() })
case .loading:
ProgressView()
case .showMessage(let messageType, let messageText):
ErrorHandlingView(messageType: messageType, messageText: messageText)
}
}.onAppear() {
viewModel.state = .idle
}
}
}
struct ErrorHandlingView: View {
@State var messageType: String
var messageText: String
@State private var messageViewImageDetails: (imageName: String, isSystemImage: Bool) = (imageName: "", isSystemImage: false)
var body: some View {
VStack {
MessageViewWithActions(imageName: messageViewImageDetails.imageName, isSystemImage: messageViewImageDetails.isSystemImage, mainMessageText: messageText)
}.onChange(of: messageType) {_ in
self.messageViewImageDetails = getImageForError()
// call more functions
}
}
private func getImageForError() -> (imageName: String, isSystemImage: Bool) {
var imageName = ""
var isSystemImage = false
switch messageType {
case "noInternetError":
imageName = "xmark.icloud"
isSystemImage = true
case "userSignedOut":
imageName = "person.crop.circle.fill.badge.xmark"
isSystemImage = true
case "userSignedIn":
imageName = "person.crop.circle.badge.checkmark"
isSystemImage = true
// more cases.
default:
imageName = "info.circle"
isSystemImage = true
}
return (imageName: imageName, isSystemImage: isSystemImage)
}
}
If "MainSetupView" is open and I receive a message ie .showMessage, "ErrorHandlingView" is displayed and I set "messageType" and "messageText" while calling ErrorHandlingView.如果“MainSetupView”打开并且我收到一条消息,即.showMessage,则会显示“ErrorHandlingView”,并且在调用ErrorHandlingView 时设置“messageType”和“messageText”。 While first message is being displayed, let's say I receive another message and "ErrorHandlingView" gets called again, now with a different message type.
在显示第一条消息时,假设我收到另一条消息并且“ErrorHandlingView”再次被调用,现在使用不同的消息类型。 However "onChange(of: messageType)" in "ErrorHandlingView" never gets called.
然而,“ErrorHandlingView”中的“onChange(of: messageType)”永远不会被调用。
"onChange(of: messageType)" calls a function "getImageForError" which tells the app which image to display based on the value of messageType. “onChange(of: messageType)”调用 function “getImageForError”,它告诉应用程序根据 messageType 的值显示哪个图像。 Since code in onChange is not getting executed, "getImageForError" never gets called and hence "messageViewImageDetails" is never populated which results in view without image.
由于 onChange 中的代码没有被执行,因此永远不会调用“getImageForError”,因此永远不会填充“messageViewImageDetails”,这会导致视图没有图像。
Any idea why is.onChange() not being executed?知道为什么 is.onChange() 没有被执行吗? What am I doing wrong?
我究竟做错了什么?
Note: I have lots of code and I am sharing pieces of code which I thought would be helpful.注意:我有很多代码,我正在分享一些我认为会有所帮助的代码。 Let me know if more code is needed.
让我知道是否需要更多代码。
Edit : Adding code for MessageViewWithActions.编辑:为 MessageViewWithActions 添加代码。
struct MessageViewWithActions: View {
// Image properties
var imageName: String?
var isSystemImage: Bool = false
// Text properties
var mainMessageText: String?
var body: some View {
ScrollView {
VStack {
Text("")
VStack {
if let imageName = imageName {
if isSystemImage {
Image(systemName: imageName)
} else {
Image(imageName)
}
}
}.frame(maxWidth: .infinity).padding(.bottom, 8)
if let mainMessageText = mainMessageText {
Text(mainMessageText).font(.subheadline).fixedSize(horizontal: false, vertical: true)
}
}
}
}
}
Changing messageType to Binding var instead of State var worked.将 messageType 更改为 Binding var 而不是 State var 有效。 Sharing updated code for future:
共享未来的更新代码:
struct MainSetupView: View {
@StateObject var viewModel: MainViewModel
@State var messageType: String
var body: some View {
VStack {
switch viewModel.state {
case .idle:
Color.clear.onAppear(perform: { viewModel.prepare() })
case .loading:
ProgressView()
case .showMessage(_, let messageText):
ErrorHandlingView(messageType: messageType, messageText: messageText)
}
}.onAppear() {
viewModel.state = .idle
}.onReceive(viewModel.$state, perform: { (value) in
switch value {
case .showMessage(let messageType, _):
self.messageType = messageType
case .idle, .loading:
print("")
}
})
}
}
struct ErrorHandlingView: View {
@Binding var messageType: String
var messageText: String
@State private var messageViewImageDetails: (imageName: String, isSystemImage: Bool) = (imageName: "", isSystemImage: false)
var body: some View {
VStack {
MessageViewWithActions(imageName: messageViewImageDetails.imageName, isSystemImage: messageViewImageDetails.isSystemImage, mainMessageText: messageText)
}.onChange(of: messageType) {_ in
self.messageViewImageDetails = getImageForError()
// call more functions
}
}
private func getImageForError() -> (imageName: String, isSystemImage: Bool) {
var imageName = ""
var isSystemImage = false
switch messageType {
case "noInternetError":
imageName = "xmark.icloud"
isSystemImage = true
case "userSignedOut":
imageName = "person.crop.circle.fill.badge.xmark"
isSystemImage = true
case "userSignedIn":
imageName = "person.crop.circle.badge.checkmark"
isSystemImage = true
// more cases.
default:
imageName = "info.circle"
isSystemImage = true
}
return (imageName: imageName, isSystemImage: isSystemImage)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.