You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中Alert展示后立即消失且文本异常的问题求助

问题分析与解决

核心问题原因

  1. Alert闪消失:SectionRowView中的showAlert是@State属性,当Person的item数组变化(删除最后一项)时,Person作为ObservableObject会触发视图重新渲染,@State会被重置为默认值false,导致Alert刚显示就被关闭。
  2. 文本粗体异常:多次触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:37:03