父对象的核心数据列表关系
Posted
技术标签:
【中文标题】父对象的核心数据列表关系【英文标题】:Core Data list relationship of Parent Object 【发布时间】:2020-08-22 09:28:04 【问题描述】:我有两个核心数据实体。一种叫做“程序”,一种叫做“锻炼”。程序与运动是一对多的关系。
我在另一个视图中将练习添加到程序中。 我有一个列出所有程序的视图和一个指向该视图的导航链接。
在这个视图中,我想列出我之前分配给程序的所有练习。但是,如果我尝试此代码,我会收到错误消息:Generic struct 'ForEach' requires that 'Exercise' conform to 'RandomAccessCollection'。
我是核心数据关系的新手,我想我可能忘记在 CoreDataClass 文件中声明某些内容。问题是我找不到这个问题的任何其他解决方案。
struct ProgramView: View
@ObservedObject var ProgramDetail: Program
var body: some View
List
ForEach(ProgramDetail.exercise!, id: \.self) exercise in
Text(exercise.name!)
这会生成所有程序的列表:
struct ProgramList: View
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Program.date, ascending: false)]) var programFetch: FetchedResults<Program>
var body: some View
NavigationView
List
ForEach(programFetch, id: \.self) program in
NavigationLink(destination: ProgramView(ProgramDetail: program))
Text(program.title!)
.navigationBarItems(
trailing:
NavigationLink(destination: CreateProgram())
Image(systemName: "plus.circle").font(.system(size: 25))
)
这是界面截图?:
Interface
【问题讨论】:
【参考方案1】:错误消息说明您必须有一个随机访问集合,以便ForEach
可以遍历该集合。
例如,Swift 的Array
符合RandomAccessCollection
协议,因此您可以使用数组。
我建议您在 Swift documentation 或 Apple's Developer website 上阅读收藏。
可能有几种方法可以实现解决方案,但也许最简单的方法如下......
struct ProgramView: View
@ObservedObject var programDetail: Program
@FetchRequest(entity: Exercise.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Exercise.name, ascending: true)],
) var allExercises: FetchedResults<Exercise>
var body: some View
List
// in this line you create an array of fetched results
// filtered to contain only exercises for programDetail
let exercisesForProgram = allExercises.filter $0.program == programDetail
ForEach(exercisesForProgram) exercise in
Text(exercise.name!)
【讨论】:
是的!这解决了我的问题。现在来测试它是否会将更改保存回 Core Data 对象... @FontFamily 它为我保存了更改。【参考方案2】:假设您没有将 To Many 关系的安排更改为 Ordered,ProgramDetail.exercise
是 NSSet?
。
您可以定义一个计算属性以将其转换为 Exercise
的数组:
extension Program
var exerciseArray: [Exercise]
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
return exercise?.sortedArray(using: [sortDescriptor]) as? [Exercise] ?? [Exercise]()
在ProgramView
现在您可以使用数组创建您的列表,如下所示:
List
ForEach(programDetail.exerciseArray, id: \.self) exercise in
Text("\(exercise.name ?? "")")
如果练习是有序关系,则ProgramDetail.exercise
将是NSOrderedSet?
。
在这种情况下,练习数组的定义就更简单了:
var exerciseArray: [Exercise]
return exercise?.array as? [Exercise] ?? [Exercise]()
【讨论】:
以上是关于父对象的核心数据列表关系的主要内容,如果未能解决你的问题,请参考以下文章