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

如何让SwiftUI List的删除按钮正常工作或隐藏?

问题根因

你遇到的问题核心是 @AppStorage 原生不支持监听自定义 Codable 数组的轻量变更:点击删除按钮触发的删除操作属于轻量修改,不会被@AppStorage捕获触发视图刷新,所以看起来无响应;而左划到底的强制删除、移动操作的变更会被系统强制触发视图刷新,所以功能正常。

解决方案

方案1:改用@State + 手动持久化

如果你的数据不需要跨页面跨App同步,直接替换@AppStorage为@State,手动做持久化即可:

struct ContentView: View {
    @State var conversions: [IDLine] = []
    
    // 启动时读取本地存储的数据
    init() {
        guard let data = UserDefaults.standard.data(forKey: "savedConversions"),
              let savedList = try? JSONDecoder().decode([IDLine].self, from: data) else {
            return
        }
        _conversions = State(initialValue: savedList)
    }
    
    // 数据变更后手动写入本地
    private func saveToLocal() {
        guard let data = try? JSONEncoder().encode(conversions) else { return }
        UserDefaults.standard.set(data, forKey: "savedConversions")
    }
    
    func deleteConversion(at offsets: IndexSet) { 
        conversions.remove(atOffsets: offsets) 
        saveToLocal()
    }
    func moveConversion(from source: IndexSet, to dest: Int) { 
        conversions.move(fromOffsets: source, toOffset: dest) 
        saveToLocal()
    }

    // 其余body等代码保持不变
}

方案2:给@AppStorage做自定义适配

如果要保留@AppStorage的用法,就把自定义数组转成@AppStorage支持的Data类型存储:

struct ContentView: View {
    // 改用Data类型做AppStorage存储
    @AppStorage("savedConversions") var conversionsData: Data = Data()
    
    // 计算属性做类型转换
    var conversions: [IDLine] {
        get {
            (try? JSONDecoder().decode([IDLine].self, from: conversionsData)) ?? []
        }
        set {
            conversionsData = (try? JSONEncoder().encode(newValue)) ?? Data()
        }
    }

    // 其余代码、删除移动方法都不用改,直接操作conversions即可
}

额外排查点

如果改完还是有问题,检查你的List行是否添加了自定义的onTapGesture等点击手势,自定义手势默认优先级高于系统删除按钮的点击手势,会导致点击无响应,可调整手势优先级或者删除冲突手势即可。

内容的提问来源于stack exchange,提问作者MarkAurelius

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:36:03