SwiftUI:如何从ContentView修改AchievementView中可识别对象的isComplete值
解决方案
要实现从ContentView修改AchievementView中成就的isComplete状态,需要调整数据结构和数据传递方式,具体操作如下:
- 修改
Achievement结构体
把isComplete从不可变的let改为可变的var,确保状态可以被修改:
struct Achievement: Identifiable { let id = UUID() let title: String let description: String var isComplete: Bool // 改为可变属性 }
- 将成就数据移至
ContentView管理
在ContentView中用@State声明成就数组作为数据源,同时添加控制sheet显示的状态变量:
struct ContentView: View { // 父视图统一管理成就数据 @State private var achievements = [ Achievement(title: "Done and Done I", description: "delete 1 task", isComplete: false), Achievement(title: "Done and Done II", description: "delete 10 tasks", isComplete: false), Achievement(title: "Done and Done III", description: "delete 50 tasks", isComplete: false), Achievement(title: "Done and Done IV", description: "delete 100 tasks", isComplete: false), Achievement(title: "Done and Done V", description: "delete 1000 tasks", isComplete: false), Achievement(title: "Busy bee I", description: "add 1 task", isComplete: false), Achievement(title: "Busy bee II", description: "add 10 tasks", isComplete: false), Achievement(title: "Busy bee III", description: "add 50 tasks", isComplete: false), Achievement(title: "Busy bee IV", description: "add 100 tasks", isComplete: false), Achievement(title: "Busy bee V", description: "add 1000 tasks", isComplete: false), Achievement(title: "Thank you", description: "rate our app", isComplete: false), Achievement(title: "Sharing is caring", description: "share your list", isComplete: false), Achievement(title: "No place like home", description: "customize taskfairy", isComplete: false) ] @State private var showAchievementView = false var body: some View { VStack(spacing: 20) { // 示例:点击按钮修改指定成就状态 Button("标记「Done and Done I」为已完成") { if let index = achievements.firstIndex(where: { $0.title == "Done and Done I" }) { achievements[index].isComplete.toggle() } } // 唤起成就视图 Button("查看成就") { showAchievementView = true } } .sheet(isPresented: $showAchievementView) { // 通过Binding传递数据给AchievementView AchievementView(achievements: $achievements) } } }
- 调整
AchievementView接收绑定数据
将原来的@State数组改为@Binding,确保视图能响应数据变化:
struct AchievementView: View { // 通过Binding接收父视图的成就数据 @Binding var achievements: [Achievement] var body: some View { List { Section(header: Text("已完成")) { ForEach($achievements) { $achievement in if achievement.isComplete { HStack { Image(systemName: "trophy.circle.fill") .scaleEffect(1.5) .padding() VStack(alignment: .leading) { Text(achievement.title) Text(achievement.description) .font(.system(size: 12)) .foregroundColor(.gray) } } } } } Section(header: Text("未完成")) { ForEach($achievements) { $achievement in if !achievement.isComplete { HStack { Image(systemName: "trophy.circle") .scaleEffect(1.5) .padding() VStack(alignment: .leading) { Text(achievement.title) Text(achievement.description) .font(.system(size: 12)) .foregroundColor(.gray) } } } } } } } }
核心逻辑说明
- 数据统一由
ContentView管理,AchievementView通过@Binding同步数据,确保修改后两边状态实时更新。 - 实际开发中,可以根据用户操作(如删除任务、添加任务的数量)自动触发对应成就的状态变更,替代示例中的按钮触发逻辑。
内容的提问来源于stack exchange,提问作者BurnDownTheWorld
相关产品推荐
相关产品推荐

