SwiftUI中Alert展示后立即消失且文本异常的问题求助
问题分析与解决
核心问题原因
- Alert闪消失:
SectionRowView中的showAlert是@State属性,当Person的item数组变化(删除最后一项)时,Person作为ObservableObject会触发视图重新渲染,@State会被重置为默认值false,导致Alert刚显示就被关闭。 - 文本粗体异常:多次触发Alert叠加显示,UI渲染冲突导致样式异常。
解决方案
把Alert的触发状态showAlert从视图的@State迁移到Person类中,作为@Published属性,让状态和数据模型绑定,避免视图重建时丢失状态;同时优化Alert的触发逻辑,确保仅在item变为空时触发一次。
修改后的关键代码
1. 更新Person类
添加@Published var showEmptyAlert: Bool = false属性:
class Person: Identifiable, ObservableObject { let id = UUID() @Published var name: String @Published var item: [TodolistItem] @Published var showEmptyAlert: Bool = false // 新增Alert状态 init(name: String, item: [TodolistItem]) { self.name = name self.item = item } }
2. 修改SectionRowView
移除本地@State private var showAlert: Bool = false,绑定person.showEmptyAlert到Alert的isPresented,调整onDelete逻辑:
struct SectionRowView: View { @State private var isExpanded: Bool = true @State private var editSheet: Bool = false @ObservedObject var person: Person var body: some View { Section(isExpanded: $isExpanded) { ForEach(person.item) { item in HStack { TodoRowView(item: item) Button { editSheet.toggle() } label: { Image(systemName: "info.circle") } .buttonStyle(BorderlessButtonStyle()) .foregroundStyle(.primary) } } .onDelete { offSet in person.item.remove(atOffsets: offSet) if person.item.isEmpty { person.showEmptyAlert = true // 触发模型中的Alert状态 } } .sheet(isPresented: $editSheet) { EditView() } Button { let newItem = TodolistItem(todoName: "Opfer", priority: "Niedrig") withAnimation { person.item.append(newItem) } } label: { HStack { Image(systemName: "plus") Text("Neues Todo hinzufügen") } .foregroundStyle(.blue) } } header: { Text(person.name) } .alert("Person löschen?", isPresented: $person.showEmptyAlert) { Button("Behalten", role: .cancel) { person.showEmptyAlert = false } Button("Löschen", role: .destructive) { person.showEmptyAlert = false // 此处可添加删除Person的逻辑,比如通知父视图移除该对象 } } message: { Text("Die Person hat alle Aufgaben erledigt, möchtest du das diese gelöscht wird?") } } }
3. 补充删除Person的逻辑(可选)
如果需要在Alert中点击"Löschen"时删除对应的Person,可在Todolist视图中添加回调逻辑:
// 在Todolist的List中修改ForEach,绑定并传递删除回调 ForEach($personen) { $person in SectionRowView(person: person, onDelete: { if let index = personen.firstIndex(where: { $0.id == person.id }) { personen.remove(at: index) } }) } // 为SectionRowView添加回调参数 struct SectionRowView: View { // ... 其他属性 let onDelete: () -> Void // 在Alert的Löschen按钮中调用回调 Button("Löschen", role: .destructive) { person.showEmptyAlert = false onDelete() } }
额外优化建议
TodolistItem作为ObservableObject,在ForEach中遍历建议使用ForEach($person.item)直接绑定,方便后续修改;- 可将
priority数组提取为全局常量或放在TodolistItem类中,避免在视图中重复定义。
内容的提问来源于stack exchange,提问作者TheRiser
相关产品推荐
相关产品推荐

