迭代 NSSet - SwiftUI 2.0

ben*_*oy9 3 core-data nsset swift swiftui

我开始研究 CoreData 并有两个实体。这些形成了 Player 之间的多对多关系:

在此处输入图片说明

和团队:

在此处输入图片说明

我试图在列表中使用 ForEach 遍历团队的球员,但我似乎无法让它工作。我一直在尝试的代码如下。我尝试的任何其他解决方案都会出现错误,例如“NSObject 类型的值没有成员名称”

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
                    
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?我想我需要将播放器类型改回播放器对象,但我不确定

Gen*_*ich 8

虽然@Asperi建议的解决方案有效,但存在一个问题。当显示由 所支持的值集合时,被剥夺了反应性更新。如果发生变化,将无法立即接受该变化并刷新自身。ForEachNSSetpeopleForEach

\n

这是因为它NSSet是一个类,而 SwiftUI 只能被动地更新结构体的属性,如此处所述

\n

我相信更好的架构是使用获取请求来获取与给定团队关联的所有玩家。该获取请求必须在 view\xe2\x80\x99s 初始化方法内部进行配置,并NSPredicate指定我们想要某个团队的玩家。如果您有多对多关系,请在您的关系中使用ANY运算符NSPredicate.

\n
struct PlayersView: View {\n    let team: Team\n    \n    @FetchRequest private var people: FetchedResults<Player>\n    \n    init(team: Team) {\n        self.team = team\n        \n        _people = FetchRequest(\n            entity: Player.entity(),\n            sortDescriptors: [NSSortDescriptor(keyPath: \\Player.name, ascending: true)],\n            predicate: NSPredicate(format: "team == %@", team)\n        )\n    }\n    \n    var body: some View {\n        NavigationView {\n            List {\n                ForEach(people) { player in\n                    Text("\\(player.name ?? "")")\n                }\n            }\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在我们可以直接插入该获取请求的结果ForEach,并且不需要执行任何类型转换。更好的是,SwiftUI 现在可以ForEach根据它注意到的更改自动更新其中的内容。

\n


Asp*_*eri 5

尝试以下操作(使用 Xcode 12.1 / iOS 14.1 编译)

ForEach(Array(team.people as? Set<Player> ?? []), id: \.self){ player in
    Text("\(player.name ?? "")" )
}
Run Code Online (Sandbox Code Playgroud)

注意:尽量避免强制解包选项,通常会导致运行时崩溃。