【问题标题】:Iterate over a NSSet - SwiftUI 2.0遍历 NSSet - SwiftUI 2.0
【发布时间】:2021-01-13 15:31:39
【问题描述】:

我开始研究 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
                    
                }
            }
        }
    }
}

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

【问题讨论】:

    标签: swift core-data swiftui nsset


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      虽然the solution 建议@Asperi 有效,但存在一个问题。在显示由NSSet 支持的值集合时,ForEach 被剥夺了响应式更新。如果people 发生更改,ForEach 将无法立即获取该更改并自行刷新。

      这是因为NSSet 是一个类,而 SwiftUI 只能响应式更新结构属性,如 here 所述。

      我相信更好的架构是使用获取请求来获取与给定球队相关联的所有球员。该获取请求必须在视图的初始化方法中配置,NSPredicate 指定我们想要某个团队的球员。如果您有 多对多 关系,请在 NSPredicate 中使用 ANY 运算符。

      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 ?? "")")
                      }
                  }
              }
          }
      }
      

      现在我们可以将该获取请求的结果直接插入ForEach,而无需进行任何类型转换。更好的是,SwiftUI 现在可以根据它注意到的变化自动更新 ForEach 的内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-26
        • 2019-11-02
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 2020-05-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多