給定
- 帶有簡單串列的視圖
- 串列中每個元素的 ItemView
- 應用模型
- 模型值(甲板)
點擊主視圖中的按鈕,預計模型會更改并將更改傳播到 ItemView。
問題是,只有當模型結構作為普通變數存盤在 ItemView 中時,更改才會傳播;但是如果我添加@State
屬性包裝器,這些就不會發生。視圖將更新但不會更改(例如資料是否已快取)。
問題 1:這是預期的行為嗎?如果是這樣,為什么?我希望 ItemView 僅在模型更改時通過觀察它拋出@State 來更新,這樣視圖將始終在串列命令它時重繪 ,即使資料未更新?
問題2:使用普通結構屬性作為模型的串列項是否正常?在視圖模型中處理陣列時,使用可觀察類會產生更多的復雜性,并且在我看來,串列重繪 /識別機制也會變得更加復雜。
在示例中,模型不需要@State,因為更改僅來自外部,在現實世界中,當視圖本身觸發更改時我需要它?
這是重現問題的精簡版本(創建一個專案并將 ContentView 替換為以下內容):
import SwiftUI
struct Deck: Identifiable {
let id: Int
var name: String
init(_ name: String, _ id: Int) {
self.name = name
self.id = id
}
}
struct ItemView: View {
// @State var deck: Deck // DOES NOT WORK !!! <-------------------
let deck: Deck // WORKS (first element is updated)
var body: some View { Text(deck.name) }
}
class Model: ObservableObject {
@Published var decks: [Deck] = getData()
static func getData(changed: Bool = false) -> [Deck] {
let firstElement = changed ? "CHANGED ELEMENT" : "0"
return [Deck(firstElement, 0), Deck("1", 1), Deck("2", 2)]
}
func changeFirst() { self.decks = Self.getData(changed: true) }
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
List {
ForEach(model.decks) { deck in
ItemView(deck: deck)
}
Button(action: model.changeFirst) {
Text("Change first item")
}
}
}
}
使用 Xcode 13 / iPhone13 模擬器 (iOS 15) 測驗
uj5u.com熱心網友回復:
問題 1
是的,這是意料之中的,因為@State
和@Published
是事實的來源。@State
斷開連接@Published
并制作副本。
問題 2 如果所有更改都在外部(單向連接),則在處理值型別時,您不需要任何型別的子類包裝器。
@Binding
如果您需要在處理struct
/value 型別時使用的雙向連接。
https://developer.apple.com/wwdc21/10022
https://developer.apple.com/documentation/swiftui/managing-user-interface-state
https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/515417.html