'Iterate over a NSSet - SwiftUI 2.0
I am starting to look at CoreData and have two entities. These form a many to many relationship between Player:
and Team:
I am trying to iterate through the players of a team using a ForEach inside a list but I can't seem to get it to work. The code I have been trying is below. Any other solutions I try I get errors such as 'Value of type NSObject has no member name'
struct PlayersView: View{
var team: Team
var body: some View{
NavigationView{
List{
ForEach(Array(team.people! as Set), id: \.self){ player in
Text("\(player.name)" ) //Error on this line
}
}
}
}
}
Any ideas? I think I need to change the player type back to the Player Object but I am not sure
Solution 1:[1]
While the solution that @Asperi suggested works, there is an issue. ForEach
is deprived of reactive updates when displaying a collection of values backed by NSSet
. If people
change, ForEach
will not be able to pick up that change and refresh itself right away.
This is because NSSet
is a class and SwiftUI can only reactively update properties that are structures, as noted here.
I believe the better architecture would be to use fetch request to get all the players associated with a given team. That fetch request would have to be configured inside of view’s initializer method, with NSPredicate
that specifies that we want players for a certain team. If you have a many-to-many relationship, use ANY operator in your NSPredicate
.
struct PlayersView: View {
let team: Team
@FetchRequest private var people: FetchedResults<Player>
init(team: Team) {
self.team = team
_people = FetchRequest(
entity: Player.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Player.name, ascending: true)],
predicate: NSPredicate(format: "team == %@", team)
)
}
var body: some View {
NavigationView {
List {
ForEach(people) { player in
Text("\(player.name ?? "")")
}
}
}
}
}
Now we can plug the results of that fetch request right into ForEach
and don’t have to do any type casting. Even better, SwiftUI can now automatically update contents of that ForEach
based on changes that it notices.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |