[英]SwiftUI - onChange not getting called
首先添加代碼以幫助更好地理解問題。
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)
}
}
如果“MainSetupView”打開並且我收到一條消息,即.showMessage,則會顯示“ErrorHandlingView”,並且在調用ErrorHandlingView 時設置“messageType”和“messageText”。 在顯示第一條消息時,假設我收到另一條消息並且“ErrorHandlingView”再次被調用,現在使用不同的消息類型。 然而,“ErrorHandlingView”中的“onChange(of: messageType)”永遠不會被調用。
“onChange(of: messageType)”調用 function “getImageForError”,它告訴應用程序根據 messageType 的值顯示哪個圖像。 由於 onChange 中的代碼沒有被執行,因此永遠不會調用“getImageForError”,因此永遠不會填充“messageViewImageDetails”,這會導致視圖沒有圖像。
知道為什么 is.onChange() 沒有被執行嗎? 我究竟做錯了什么?
注意:我有很多代碼,我正在分享一些我認為會有所幫助的代碼。 讓我知道是否需要更多代碼。
編輯:為 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)
}
}
}
}
}
將 messageType 更改為 Binding var 而不是 State var 有效。 共享未來的更新代碼:
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.