Я просто потратил два дня, пытаясь понять это, надеюсь, кто-то там может мне помочь. Я уверен, что этот базис c должен быть выполнимым, и мне не хватает некоторой концепции базис c ...
Использование XCode 11.4 на macOS , но Я подозреваю, что это применимо и к iOS.
Я сократил источник до минимума, чтобы проиллюстрировать проблему.
У меня есть список элементов в главный подробный вид, где список элементов выбирается из одного источника, и как только пользователь нажимает на один из них, подробности выбираются из второго источника и отображаются в подробном виде справа.
Ожидаемый результат
Когда я нажимаю на элемент, тело элемента отображается в подробном представлении справа.
Фактический результат
Когда я нажимаю на первый элемент, справа отображается правильное тело. Но метод ItemDetailStore.load () вызывается дважды!
Когда я нажимаю на второй и третий элемент, подробный вид остается неизменным.
Source
import SwiftUI
struct ContentView: View {
@State var selectedItem: Item?
var body: some View {
NavigationView {
ItemList(selectedItem: $selectedItem)
if selectedItem != nil {
ItemDetail(selectedItem: $selectedItem)
}
}
}
}
struct ItemList: View {
@Binding var selectedItem: Item?
var items = [
Item(itemId: 0, title: "Item #0", body: "Empty."),
Item(itemId: 1, title: "Item #1", body: "Empty."),
Item(itemId: 2, title: "Item #2", body: "Empty.")
]
var body: some View {
List(selection: $selectedItem) {
ForEach(Array(items.enumerated()), id: \.element) { index, item in
ItemRow(item: item)
}
}
.listStyle(SidebarListStyle())
}
}
struct ItemRow: View {
var item: Item
var body: some View {
Text("\(item.title)")
.padding(12)
}
}
struct ItemDetail: View {
@EnvironmentObject var itemDetailStore: ItemDetailStore
@Binding var selectedItem: Item?
var body: some View {
VStack {
if itemDetailStore.items.count > 0 {
Text(itemDetailStore.items[0].body)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
if self.selectedItem != nil {
self.itemDetailStore.load(id: self.selectedItem!.itemId)
}
}
}
}
struct Item: Codable, Hashable {
var itemId: Int
var title: String
var body: String
}
class ItemDetailStore: ObservableObject {
@Published var items = [Item]()
var itemsList = [
Item(itemId: 0, title: "Item #0", body: "This is an excellent item #0."),
Item(itemId: 1, title: "Item #1", body: "This is an excellent item #1."),
Item(itemId: 2, title: "Item #2", body: "This is an excellent item #2.")
]
func load(id: Int) {
self.items = [itemsList[id]]
print("\(self.items[0].title) loaded.")
}
}
И в AppDelegate я внедряю среду:
let contentView = ContentView().environmentObject(ItemDetailStore())
Кажется, что виновником является модификатор onAppear в ItemDetail, так как он вызывается только тогда, когда первый элемент в список нажимается. Разве представление не должно обновляться каждый раз, когда selectedItem изменяется?
Любая обратная связь высоко ценится.