SwiftUI 4: можно ли делать несколько вызовов .navigationDestination() на разных уровнях иерархии представлений?
Интересно, можно ли позвонитьnavigationDestination()
несколько раз на разных уровнях иерархии представлений? Я гуглил, но все примеры, которые я нашел в сети, называли это на верхнем уровне внутриNavigationStack
. Я попробовал следующий код. Это сработало нормально, но я не уверен, случайно это или намеренно. Я хотел бы кодировать таким образом, потому что это помогает организовать код.
struct ID<Value>: Hashable, Equatable {
let uuid: UUID
init() {
uuid = UUID()
}
}
typealias CategoryID = ID<Category>
typealias ItemID = ID<Item>
struct Catalog {
var categories: [Category]
func getCategory(_ categoryID: CategoryID) -> Category? {
return categories.first { $0.id == categoryID }
}
func getItem(_ categoryID: CategoryID, _ itemID: ItemID) -> Item? {
guard let category = getCategory(categoryID) else { return nil }
return category.items.first { $0.id == itemID }
}
}
struct Category: Identifiable {
var id: CategoryID = .init()
var name: String
var items: [Item]
}
struct Item: Identifiable {
var id: ItemID = .init()
var name: String
}
func createTestData() -> Catalog {
let categories = [
Category(name: "Category A", items: [Item(name: "Item a1"), Item(name: "Item a2")]),
Category(name: "Category B", items: [Item(name: "Item b1"), Item(name: "Item b2")])
]
return Catalog(categories: categories)
}
struct ContentView: View {
@State var catalog: Catalog = createTestData()
var body: some View {
NavigationStack {
List {
ForEach(catalog.categories) { category in
NavigationLink(category.name, value: category.id)
}
}
// This is the typical place to make one or multiple calls of navigationDestination().
.navigationDestination(for: CategoryID.self) { categoryID in
CategoryView(categoryID: categoryID, catalog: $catalog)
}
}
}
}
struct CategoryView: View {
let categoryID: CategoryID
@Binding var catalog: Catalog
var body: some View {
if let category = catalog.getCategory(categoryID) {
List {
ForEach(category.items) { item in
NavigationLink(item.name, value: item.id)
}
}
// Q: is it OK to call navigationDestination() here?
.navigationDestination(for: ItemID.self) { itemID in
ItemView(categoryID: categoryID, itemID: itemID, catalog: $catalog)
}
}
}
}
struct ItemView: View {
let categoryID: CategoryID
let itemID: ItemID
@Binding var catalog: Catalog
var body: some View {
if let item = catalog.getItem(categoryID, itemID) {
Text(item.name)
}
}
}
Обратите внимание, что в коде используется общий тип идентификатора, потому что иначе SwifUI не смог бы отличитьnavigationDestination(for: CategoryID)
иnavigationDestination(for: ItemID)
.