使用 ForEach SwiftUI Core Data 仅更改列表中的一项
Posted
技术标签:
【中文标题】使用 ForEach SwiftUI Core Data 仅更改列表中的一项【英文标题】:Only change one item in List using ForEach SwiftUI Core Data 【发布时间】:2020-01-03 19:28:52 【问题描述】:我有一个循环视图,使用 ForEeach 在使用 Core Data 关系的数组中显示列表。
视图显示了每个循环中的所有元素,我需要将它们单独分割出来,同时能够保持切换按钮而不是同时切换所有目标。
编辑:我想出了如何制作它,所以它们都没有迭代和显示,但现在切换任何按钮都会切换它们。 :(
游戏目标详情
import SwiftUI
import CoreData
struct GameGoalsDetail: View
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Game.entity(), sortDescriptors: []) var games: FetchedResults<Game>
@State private var showingAddGoal = false
@State private var goalComplete : Bool = false
@ObservedObject var game: Game
var body: some View
VStack
Text(self.game.gameName ?? "No Game Name").font(.title)
Text(self.game.gameDescription ?? "No Game Description").font(.subheadline)
List GameGoalListView(game: self.game).environment(\.managedObjectContext, self.moc)
Button("Add Game Goal")
self.showingAddGoal.toggle()
.sheet(isPresented: $showingAddGoal)
AddGameGoalsView(game: self.game).environment(\.managedObjectContext, self.moc)
游戏目标列表视图
import SwiftUI
import CoreData
struct GameGoalListView: View
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Game.entity(), sortDescriptors: []) var games: FetchedResults<Game>
@ObservedObject var game: Game
@State private var goalComplete : Bool = false
var body: some View
VStack
ForEach(game.goalArray, id: \.self) goal in
HStack
Text(goal.goalName ?? "No Goal Name")
Spacer()
Text("Complete:").font(.caption)
Image(systemName: self.goalComplete ? "checkmark.square.fill" : "app").onTapGesture
self.goalComplete.toggle()
print(self.goalComplete)
这是正在发生的事情的屏幕截图:
点击后:
我试图让它在添加目标时显示在列表中,然后我可以通过按钮选择目标是否完成。 所以每个游戏都会有一个由用户输入添加的不同目标的列表。
非常感谢帮助并可以根据要求提供更多信息。
【问题讨论】:
您需要添加更多上下文。很难理解你在这里问什么,更不用说你的代码应该做什么了。 @Pierce 我添加了更多上下文。看看 Core Data 类会有帮助吗? 现在我有点理解您想要做什么,但我不一定理解您在尝试执行此操作时遇到的问题。我不知道展示你的 CD 课程是否真的有帮助,我的直觉认为这并不重要,听起来你的逻辑或 UI 的设置方式可能有问题? 您正在外部和内部视图中迭代目标列表。你不想要这些循环之一吗?你能展示一下输出应该是什么样子吗? @Paulw11 我对其进行了编辑,以便仅迭代内部视图,但现在所有项目都被切换,而不仅仅是一个。 【参考方案1】:我不得不重做这么多,但在一位出色的 Redditor 的帮助下,我弄明白了。
游戏目标详情
我不需要获取请求,因为它是从视图中传入的。 不需要@State,因为我应该直接使用 CoreData 信息。List
ForEach(game.goalArray, id: \.self) goal in
GameGoalListView(goal: goal)
只需要传入的GameGoalListView(goal:goal),因为我重做了GameGoalListView。
游戏目标列表视图
再次摆脱了@State 和@FetchRequest GameGoalsDetail 中的列表是显示每个目标的内容,因此此视图中不需要额外的 ForEach。此视图只需要显示需要显示的内容以及从 CoreData 中提取的信息。@ObservedObject 是目标而不是游戏。 onTapGesture 正在从 CoreData 而不是状态访问goal.goalComplete(这会创建一个新的真相来源(观看 WDCC 视频))。
然后 onReceive 和 objectWillChange 让目标知道每次点击按钮时它都会发生变化。
struct GameGoalListView: View
@Environment(\.managedObjectContext) var moc
@ObservedObject var goal: Goal
var body: some View
VStack
HStack
Text(goal.goalName ?? "No Goal Name")
Spacer()
Text("Complete:").font(.caption)
Image(systemName: self.goal.goalComplete ? "checkmark.square.fill" : "app").onTapGesture
self.goal.goalComplete.toggle()
print(self.goal.goalComplete)
.onReceive(self.goal.objectWillChange)
try? self.moc.save()
正如我所说,帮助来自 Redditor,我希望这可以帮助某人找出我的问题并修复他们的错误。
【讨论】:
谢谢,这正是我想要的。很好的解决方案! for id:\.self
你能用\.objectID
代替吗?以上是关于使用 ForEach SwiftUI Core Data 仅更改列表中的一项的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 中,如何在 LinkedList 中“Foreach”节点?