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