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

如何让新增至Chosen列表的项立即支持拖拽与删除?

问题

我有一个包含两个分区的列表:

  • chosen选项区:支持重排与删除操作
  • suggested选项区:可将区内项添加至chosen区

目前遇到的问题是:从suggested区新增到chosen的项(比如"five""six")无法立即支持拖拽与删除编辑。另外我发现,如果把suggested分区里的ForEach(filteredSuggestions(), id: \.self)换成ForEach(suggested, id: \.self),chosen分区的显示会符合预期,但suggested分区的内容就不对了。

相关代码如下:

struct EditorView: View {
    @State var chosen = ["one", "two", "three", "four"]
    let suggested = ["five", "six", "seven", "eight"]

    var body: some View {
        List {
            Section {
                ForEach(chosen, id: \.self) { item in Text(item) }
                    .onDelete{ _ in }
                    .onMove{ _, _ in }
            } header: { Text("chosen") }
            Section {
                ForEach(filteredSuggestions(), id: \.self) { item in
                    HStack(spacing: 14) {
                        Button { chosen.append(item) }
                        label: {
                            Image(systemName: "plus.circle.fill")
                                .imageScale(.large)
                                .foregroundStyle(.green)
                        }
                        Text(item)
                    }
                }
            } header: { Text("suggested") }
        }
        .environment(\.editMode, .constant(.active))
    }
    
    private func filteredSuggestions() -> [String] {
        return suggested.filter { item in
            !chosen.contains(item)
        }
    }
}
解决方法

问题根源在于ForEach的数据源处理和SwiftUI的视图更新逻辑:用方法返回过滤后的数组时,每次chosen变化都会生成新数组实例,导致SwiftUI刷新视图时,chosen分区的新增项没有正确关联编辑状态。可以通过以下步骤修复:

  1. 将过滤方法改为计算属性
    把filteredSuggestions()改成计算属性,让SwiftUI更高效地追踪数据源变化,避免频繁生成新数组实例:

    private var filteredSuggestions: [String] {
        suggested.filter { !chosen.contains($0) }
    }
    
  2. 完善编辑逻辑并添加状态更新动画
    原来的onDelete和onMove是空实现,需要补充实际逻辑;同时给添加操作加上动画,确保SwiftUI正确更新chosen分区的视图状态,让新增项立即获得编辑能力。

完整修复后的代码:

struct EditorView: View {
    @State var chosen = ["one", "two", "three", "four"]
    let suggested = ["five", "six", "seven", "eight"]

    private var filteredSuggestions: [String] {
        suggested.filter { !chosen.contains($0) }
    }

    var body: some View {
        List {
            Section {
                ForEach(chosen, id: \.self) { item in
                    Text(item)
                }
                .onDelete(perform: deleteItem)
                .onMove(perform: moveItem)
            } header: { Text("chosen") }

            Section {
                ForEach(filteredSuggestions, id: \.self) { item in
                    HStack(spacing: 14) {
                        Button {
                            withAnimation {
                                chosen.append(item)
                            }
                        } label: {
                            Image(systemName: "plus.circle.fill")
                                .imageScale(.large)
                                .foregroundStyle(.green)
                        }
                        Text(item)
                    }
                }
            } header: { Text("suggested") }
        }
        .environment(\.editMode, .constant(.active))
    }

    private func deleteItem(at offsets: IndexSet) {
        chosen.remove(atOffsets: offsets)
    }

    private func moveItem(from source: IndexSet, to destination: Int) {
        chosen.move(fromOffsets: source, toOffset: destination)
    }
}

修复说明

  • 计算属性filteredSuggestions让SwiftUI能精准追踪数据源变化,避免不必要的视图刷新
  • withAnimation确保添加项时视图平滑过渡,同时让SwiftUI正确识别chosen数组的更新,为新增项绑定编辑状态
  • 实现deleteItem和moveItem方法,让删除、重排功能真正可用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:14:56