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).

0 ответов

Другие вопросы по тегам