Reputation: 359
I am looping through an array of Models and I want a different navigation destination for each one. What is the best approach to that? Here is the model
struct HomePageGridItem: Identifiable {
var id: Int
var image: String
var title: String
var desc: String
}
And here is what I get when I try to add a destination
I don't know what I'm missing here.
Upvotes: 0
Views: 1166
Reputation: 298
I'd agree that you shouldn't do this - the view should handle routing, whereas the model should inform routing.
However, for your learning, it may be useful to understand a potential solution and what the error you're getting means - it comes up a lot in SwiftUI development.
Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
This error is displayed when the protocol in question (View
in this case), has an associated type defined internally, and you have not set a requirement for what this associated type should be. An example of a protocol with an associated type might be the Identifiable
protocol...
protocol Identifiable {
associatedtype ID
var id: ID { get set }
}
As you can see, there is an associated type defined - ID
. This is a generic, meaning it can take on any form as needed for this protocol's use. In each use of the protocol, the associatedtype (or generic) can only be defined upon initialization of the conforming object OR in your case, the declaration of a variable. An example implementation of Identifiable
might assign ID
as type String
. In that case, the id
variable would be of type String
.
As stated, the protocol in your situation is View
. It's definition looks something like this...
protocol View {
associatedtype Body
var body: Body
}
The generic in this case is Body
, which must be defined upon definition of the View
. Read more about protocols with associated types and their uses here:
https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID189
In your case, you must define your property destination
as a concrete implementation of protocol View
, because the associated type must be static for the definition of your variable. One useful concrete implementation of View
is AnyView
. Your model would look like this...
struct HomePageGridItem: Identifiable {
var id: Int
var image: String
var title: String
var desc: String
var destination: AnyView
}
To cast 'any view' as an AnyView
, simply do this...
AnyView(Color.red)
Now, rather than the view being of type Color
, it will be of type AnyView
. If you want to use your model, all you would have to do is wrap your desired view in an instance of AnyView
when assigning it to the HomePageGridItem.destination
variable.
Upvotes: 1