有一種奇怪的情況,如果您通過另一個視圖顯示一個視圖,當使用 onAppear 設定值時,第二個視圖的內容(3 個專案的串列)將不會顯示。我猜 SwiftUI 會感到困惑,因為第二個視圖 onAppear 是在第一個視圖 onAppear 之前呼叫的,但我仍然認為這很奇怪,因為兩個視圖資料都只在它們自己的視圖中使用。此外,如果我不使用視圖模型,而是直接在視圖中使用狀態設定資料,也沒有問題,但是還有另一個問題是視圖模型宣告必須被注釋掉,否則我會得到“執行緒 1 :EXC_BAD_ACCESS(代碼=1,地址=0x400000008)”。此外,如果我在顯示第二個資料之前在第一個視圖中檢查設定在那里的資料的 nil,那么第二個視圖將在您第一次導航時顯示(到包含第二個的第一個視圖),但不會顯示其他時間。我還嘗試洗掉內容視圖并直接從 FirstView 開始,然后螢屏只是黑色。我想了解為什么會發生這些問題,通過 init 設定資料可以作業,但是會在導航到之前呼叫 init,因為 NavigationView 就是這樣作業的,反過來我想我可以通過使用延遲視圖來解決,但有些情況下我也想用.task在后臺做一些事情,它和.onAppear有同樣的問題。無論如何,我想避免解決問題并了解問題。請參閱評論以獲得更好的解釋:我還嘗試洗掉內容視圖并直接從 FirstView 開始,然后螢屏只是黑色。我想了解為什么會發生這些問題,通過 init 設定資料可以作業,但是會在導航到之前呼叫 init,因為 NavigationView 就是這樣作業的,反過來我想我可以通過使用延遲視圖來解決,但有些情況下我也想用.task在后臺做一些事情,它和.onAppear有同樣的問題。無論如何,我想避免解決問題并了解問題。請參閱評論以獲得更好的解釋:我還嘗試洗掉內容視圖并直接從 FirstView 開始,然后螢屏只是黑色。我想了解為什么會發生這些問題,通過 init 設定資料可以作業,但是會在導航到之前呼叫 init,因為 NavigationView 就是這樣作業的,反過來我想我可以通過使用延遲視圖來解決,但有些情況下我也想用.task在后臺做一些事情,它和.onAppear有同樣的問題。無論如何,我想避免解決問題并了解問題。請參閱評論以獲得更好的解釋:反過來,我想我可以通過使用延遲視圖來解決這個問題,但是在某些情況下,我也想在后臺使用 .task 做一些事情,并且它與 .onAppear 有相同的問題。無論如何,我想避免解決問題并了解問題。請參閱評論以獲得更好的解釋:反過來,我想我可以通過使用延遲視圖來解決這個問題,但是在某些情況下,我也想在后臺使用 .task 做一些事情,并且它與 .onAppear 有相同的問題。無論如何,我想避免解決問題并了解問題。請參閱評論以獲得更好的解釋:
struct ContentView: View {
var body: some View {
NavigationView {
// If I directly go to SecondView instead the list shows
NavigationLink(destination: FirstView()) {
Text("Go to first view")
}
}
}
}
class FirstViewViewModel: ObservableObject {
@Published var listOfItems: [Int]?
func updateList() {
listOfItems = []
}
}
struct FirstView: View {
@ObservedObject var viewModel = FirstViewViewModel()
// If I have the state in the view instead of the view model there is no problem.
// Also need to comment out the view model when using the state otherwise I get Thread 1: EXC_BAD_ACCESS runtime exception
//@State private var listOfItems: [Int]?
var body: some View {
// Showing SecondView without check for nil and it will never show
SecondView()
// If I check for nil then the second view will show the first time its navigated to, but no other times.
/*Group {
if viewModel.listOfItems != nil {
SecondView()
} else {
Text("Loading").hidden() // Needed in order for onAppear to trigger, EmptyView don't work
}
}*/
// If I comment out onAppear there is no problem
.onAppear {
print("onAppear called for first view after onAppear in second view")
viewModel.updateList()
// listOfItems = []
}
}
}
class SecondViewViewModel: ObservableObject {
@Published var listOfItems = [String]()
func updateList() {
listOfItems = ["first", "second", "third"]
}
}
struct SecondView: View {
@ObservedObject var viewModel = SecondViewViewModel()
// If I set the items through init instead of onAppear the list shows every time
init() {
// viewModel.updateList()
}
var body: some View {
Group {
List {
ForEach(viewModel.listOfItems, id: \.self) { itemValue in
VStack(alignment: .leading, spacing: 8) {
Text(itemValue)
}
}
}
}
.navigationTitle("Second View")
.onAppear {
viewModel.updateList()
// The items are printed even though the view don't show
print("items: \(viewModel.listOfItems)")
}
}
}
uj5u.com熱心網友回復:
我們不在 SwiftUI 中使用視圖模型物件。對于我們使用的 View 的資料瞬態,@State并使@BindingView 資料結構表現得像一個物件。
僅供參考,使用初始化物件@ObservedObject是導致記憶體泄漏的錯誤,每次View結構初始化時都會將其丟棄。當我們創建一個組合加載器/提取器物件時,我們希望其生命周期與我們使用初始化物件的視圖相關聯@StateObject。
此外,您不能id: \.self對ForEach值型別陣列進行處理,因為它會在資料更改時崩潰。您必須為您的資料創建一個結構,以便Identifiable與ForEach. 或者,如果你真的想要一個靜態的ForEach,你可以這樣做ForEach(0..<5) {
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/448207.html
