I am interested in storing one of several SwiftUI views as a destination for a dynamically generated button. Programmatically, I create a struct to store the modules to be created:
struct Module: Identifiable {
var id: Int
var name: String
var destinationView = NewsView() // var destinationView: View - - - does not work
}
An array exists which stores the modules to be created on the home page view:
ForEach(sessionParts[currentSessionPart].modules) { module in
Group {
NavigationLink(destination:
module.destinationView
) {
ZStack {
HomeScreenNav() // View defining button
Text("\(module.name)")
.font(.largeTitle)
.color(Color.black)
}
}
}
}
This works correctly and a button is created that links to the NewsView view. But if I try to define the variable by type View, it does not work. Nor can I overwrite the variable with a different View.
I have stretched my limited Swift skills and tried a few things, but have been unable to get closer to a solution. Thanks for any help.
You cannot declare a property of type View because View is a protocol with an associated type. Instead, you need to declare destinationView to be of a type that conforms to the View protocol. Sometimes this is hard, because views often have complicated types like VStack<TupleView<(Text, Text)>> (and that's not even a particularly complicated example).
In your case, it's easy, because you have created a separate NewsView type that conforms to View. So you can just say this:
var destinationView: NewsView = NewsView()
However, this means that destinationView can only hold a value of type NewsView. If you want to change it to an OldsView when the user clicks a button, you can't, because destinationView cannot hold an OldsView.
If you want destinationView to be able to hold any value whose type conforms to View, you need to use the type-erasing wrapper AnyView. If you have any value whose type conforms to View, you can wrap it in an AnyView to hide the specific type:
var destinationView: AnyView = AnyView(NewsView())
Then you can later assign some other view to it:
func buttonWasTapped() {
destinationView = AnyView(OldsView())
}