SwiftUI切换showAnswer时所有答案同步显示,如何单独控制每个问题的答案显隐
SwiftUI 抽认卡单个答案显隐控制解决方案
问题根因
- 你当前定义的
showAnswer是ItemsView层面的全局状态,所有列表卡片共用这一个状态变量,所以切换时所有卡片的答案会同步显隐。 - 给问答结构体加Bool属性后报错,是因为List遍历得到的
item是值类型的临时不可变拷贝,无法直接修改它的属性,需要通过视图模型修改对应数组元素的属性。
解决方案
方案1:拆分独立子视图(轻量首选)
把单个抽认卡项拆成独立子视图,每个子视图自己管理答案显隐状态,互不干扰,代码改动最小:
首先定义子视图:
// 单个抽认卡视图,自己管理显隐状态 struct FlashCardItemView: View { let item: FlashCardItem // 替换为你实际的问答模型名 @State private var showAnswer = false var body: some View { VStack(alignment: .leading, spacing: 10) { Button(item.question) { showAnswer.toggle() } showAnswer ? Text(item.answer) : Text(" ") } } }
修改原ItemsView代码:
struct ItemsView: View { @StateObject var vm = ItemViewModel() var body: some View { List(vm.items) { item in FlashCardItemView(item: item) } .onAppear { vm.fetch()} } }
方案2:视图模型统一管理状态(适合需要持久化/全局访问场景)
如果需要在视图模型层面记录每个卡片的显隐状态,按以下步骤修改:
- 给问答模型添加可变的显隐控制属性:
struct FlashCardItem: Identifiable { let id = UUID() let question: String let answer: String var isShowAnswer: Bool = false // 必须用var声明为可变属性 }
- 在
ItemViewModel中新增切换显隐状态的方法:
class ItemViewModel: ObservableObject { @Published var items: [FlashCardItem] = [] func toggleAnswer(for itemId: UUID) { guard let index = items.firstIndex(where: { $0.id == itemId }) else { return } items[index].isShowAnswer.toggle() } // 原有fetch等方法保持不变 func fetch() { // 原有获取数据逻辑 } }
- 修改原
ItemsView的交互逻辑:
struct ItemsView: View { @StateObject var vm = ItemViewModel() var body: some View { List(vm.items) { item in VStack(alignment: .leading, spacing: 10) { Button(item.question) { vm.toggleAnswer(for: item.id) } item.isShowAnswer ? Text(item.answer) : Text(" ") } } .onAppear { vm.fetch()} } }
内容的提问来源于stack exchange,提问作者William Allen
相关产品推荐
相关产品推荐

