我真的很難理解List(selection:)導致選擇系結更新的原因。
我在https://developer.apple.com/documentation/swiftui/building_a_great_mac_app_with_swiftui取消選擇 Apple 示例代碼
該專案是Session2/Part2-End/GardenApp.xcodeproj
左側有一個側邊欄,右側有主要詳細視圖。ContentView看起來像這樣:
struct ContentView: View {
@EnvironmentObject var store: Store
@SceneStorage("selection") private var selectedGardenID: Garden.ID?
@AppStorage("defaultGarden") private var defaultGardenID: Garden.ID?
var body: some View {
NavigationView {
Sidebar(selection: selection)
GardenDetail(garden: selectedGarden)
}
}
private var selection: Binding<Garden.ID?> {
Binding(get: { selectedGardenID ?? defaultGardenID }, set: { selectedGardenID = $0 })
}
private var selectedGarden: Binding<Garden> {
$store[selection.wrappedValue]
}
}
和這樣的側邊欄:
struct Sidebar: View {
@EnvironmentObject var store: Store
@SceneStorage("expansionState") var expansionState = ExpansionState()
@Binding var selection: Garden.ID?
var body: some View {
List(selection: $selection) {
DisclosureGroup(isExpanded: $expansionState[store.currentYear]) {
ForEach(store.gardens(in: store.currentYear)) { garden in
SidebarLabel(garden: garden)
.badge(garden.numberOfPlantsNeedingWater)
}
} label: {
Label("Current", systemImage: "chart.bar.doc.horizontal")
}
Section("History") {
GardenHistoryOutline(range: store.previousYears, expansionState: $expansionState)
}
}
.frame(minWidth: 250)
}
}
現在SidebarLabel視圖沒有任何對選擇系結的參考;但是,當您單擊其中一個標簽時,選擇會更新,并且系結會傳播到ContentView,因此GardenDetai視圖會使用新選擇進行更新。
My question is: how does clicking on one of the sidebar items cause the selection binding to be updated since there is no reference to the selection binding? Does the ForEach have anything to do with it?
If so, how can I add 'ad hoc' items that do not participate in a ForEach like this? If not, what is going on?
uj5u.com熱心網友回復:
List并ForEach在這里一起作業。該串列看到它有一個 ForEach over Garden,并且 ForEach 自動提供了一個.tag(garden.id)
純粹的List形式看起來像這樣,并且可能更清楚地顯示發生了什么。我包括了一個明確的.tag(),但這將自動生成。
struct Sidebar2: View {
@EnvironmentObject var store: Store
@Binding var selection: Garden.ID?
var body: some View {
List(store.gardens(in: store.currentYear), selection: $selection) { garden in
SidebarLabel(garden: garden)
.tag(garden.id) // << not needed, will be done implicitly
.badge(garden.numberOfPlantsNeedingWater)
}
.frame(minWidth: 250)
}
}
由于這些部分,List它被用作ForEach. 但原理還是一樣的。其自動生成的ForEach指標id最多List并設定selection。
如果你想向側邊欄添加自定義元素,你可以給它們一個明確的.tag......你只需要找出在哪里解碼這些自定義標簽以及在詳細視圖中相應地顯示什么。
uj5u.com熱心網友回復:
您可以在List 的檔案中找到更多詳細資訊,請查看“支持多維串列”下的示例。
但基本上,這就是正在發生的事情:
該行將
List(selection: $selection)選定的花園存盤在 的selection變數中SideBar。的
selection變數SideBar是變數 in的系結(見第 1 行),所以當前者改變時,后者也隨之更新。selectionContentViewSidebar(selection: selection)selectedGarden變數 ofContentView是一個計算屬性,它回傳索引處的花園-selection.wrappedValue如果selection的值發生變化,則selectedGarden回傳不同的值。該
GardenDetail視圖根據selectedGarden傳遞給它的變數顯示詳細資訊:GardenDetail(garden: selectedGarden).
改變selectioninSideBar也改變了selectionin ContenView,這使得selectedGarden回傳一個不同的花園,更新GardenDetail視圖。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/441777.html
