Right now I'm learning NavigationStacks in SwiftUI and I'm wondering if there is a elegant solution for passing the title of the NavigationLink from the previous view.
Consider the following example:
struct Foo: Hashable, Identifiable {
let id = UUID().uuidString
let name: String
let bar: [String]
}
let exampleData: [Foo] = [
Foo(name: "Item 1", bar: ["Lorem", "ipsum"]),
Foo(name: "Item 2", bar: ["Lorem2", "ipsum2"])
]
struct MyNavigationView: View {
@State private var data = exampleData
var body: some View {
NavigationView {
List(data) { d in
NavigationLink(destination: {
List{
ForEach(d.bar, id: \.self) { val in
Text(val)
}
}.navigationTitle(d.name)
}) {
Text(d.name)
}
}
}
}
}
I created a NavigationStack and would like the destination to have d.name as its title:
struct MyNavigationStackView: View {
@State private var data = exampleData
var body: some View {
NavigationStack {
List(data) { d in
NavigationLink(value: d.bar) {
Text(d.name)
}
}
.navigationDestination(for: Foo.self) { elements in
// I cannot use Foo.self as a destination since it's already used for a different view
}
.navigationDestination(for: [String].self) { elements in
List(elements, id: \.self) { e in
Text(e)
} // <- I would like this list to have d.name as a navigationTitle like the NavigationView has
}
}
}
}
Is there some clever way to solve this without modifying my model?
CodePudding user response:
The solution can come by wrapping Foo into an auxiliary struct, let's call it WrappedFoo. When you pass the auxiliary struct, you unwrap it into the value of Foo, and read the properties one by one.
Like this...
This is the auxiliary struct:
struct WrappedFoo: Hashable {
// It contains only one property of type Foo
let foo: Foo
init(_ foo: Foo) {
self.foo = foo
}
}
How to use it:
var body: some View {
NavigationStack {
List(data) { d in
// Pass the auxiliary struct
NavigationLink(value: WrappedFoo(d)) {
Text(d.name)
}
}
.navigationDestination(for: Foo.self) { elements in
// I cannot use Foo.self as a destination since it's already used for a different view
}
// Use the auxiliary struct and get the value of the Foo property
.navigationDestination(for: WrappedFoo.self) { wFoo in
List(wFoo.foo.bar, id: \.self) { e in
Text(e)
}
// "Unwrap" Foo to get the name
.navigationTitle(wFoo.foo.name)
}
}
}
