Reputation: 985
I have a SwiftUI view where the bulk of the logic displays a list of recipes with a LazyVGrid
. The code looks something like this:
struct RecipeGrid: View {
let recipes: [Recipe]
var body: some View {
return LazyVGrid {
ForEach(countries) { country in
Text(recipe.title)
}
}
}
}
This is the hello world of SwiftUI. Straightforward stuff. Two real-world requirements make things a bit more interesting/challenging.
First, we have over 20,000 recipes. So we don't want to pass everything in as an array, as suggested by 1 and 2.
Second, there are two different ways we get the recipes
.
The first is to show the most popular recipes using a FetchRequest
. It looks something like this:
@FetchRequest(sortDescriptors: [SortDescriptor(\.likes, order: .reverse)])
private var recipes: FetchedResults<Recipe>
The second is to get all recipes using the same ingredient. There is a ManyToMany relationship between Ingredient
and Recipe
. The declaration of Ingredients
looks like this:
class Ingredient: Entity {
@NSManaged var recipes: NSOrderedSet
}
I am wondering what would be the recommended way to declare the recipes
inside RecipeGrid
so that it will support both the use cases above.
I have tried the following
struct RecipeGrid: View {
let recipes: RandomAccessCollection
...
}
The above doesn't work. Swift gives the following error message: Protocol 'RandomAccessCollection' can only be used as a generic constraint because it has Self or associated type requirements
.
What is the best practice way to approach this? I guess another way to ask my question is:
How do I declare the associated type for RandomAccessCollection?
Upvotes: 0
Views: 231
Reputation: 985
Thanks to @Asperi's help. I figured out a way to achieve what I had in mind.
There are two parts to the answer.
The first is to rewrite RecipeGrid
's signature to bind to the RandomAccessCollection
protocol, Based on passing FetchedResult
to Preview.
This opens up the possibility to test the view using an array and FetchedResult
.
struct RecipeGrid<Recipes: RandomAccessCollection>: View where RandomAccessCollection.Element == Recipe {
let recipes: Recipes
...
}
The second part is to give up using the CoreData relationship Ingredient.recipes
. The recipes
is of type NSOrderedSet
, which does not conform to the RandomAccessCollection
protocol.
The swift-collections
' OrderedSet
does support RandomAccessCollection
but unfortunately it doesn't work with CoreData.
I rewrote the code to have a second FetchedResult
to replace the ingredient.recipes
call.
Upvotes: 2