遍历 NSSet - SwiftUI 2.0
Posted
技术标签:
【中文标题】遍历 NSSet - SwiftUI 2.0【英文标题】:Iterate over a 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
有什么想法吗?我想我需要将播放器类型改回播放器对象,但我不确定
【问题讨论】:
【参考方案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
的内容。
【讨论】:
以上是关于遍历 NSSet - SwiftUI 2.0的主要内容,如果未能解决你的问题,请参考以下文章
尝试删除最后一个元素时,带有子项的 SwiftUI (2.0) 列表崩溃
使用 SwiftUI 2.0 和 Core Data 预填充数据
当 Picker selectedValue 更改时,SwiftUI 2.0 App 崩溃
SwiftUI 2.0 中的 navigationBarTitle 和 navigationTitle 有啥区别? [复制]