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

SwiftUI问题:移动列表项后编辑模式控件为何消失?

问题:SwiftUI编辑模式控件移动后消失

现象与环境

  • iOS 15.5/15.6模拟器及物理设备:移动列表项后,编辑模式的删除按钮、拖拽手柄消失
  • iOS 16.0 beta 3:点击自定义Edit按钮后,编辑控件显示随即消失(未操作列表项)
  • 开发环境:Xcode 13.4.1/14.0 beta 3,macOS 12.5(Intel处理器)
  • 例外情况:移除NavigationView或使用系统默认EditButton()时,功能正常运行

问题代码

import SwiftUI

struct ContentView: View {
    @Environment(\.editMode) var editMode
    @State private var items = [1, 2, 3]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: \.self) {
                    Text("Item \($0)")
                }
                    .onDelete {_ in }
                    .onMove(perform: moveItems)
            }.toolbar {
                //EditButton()
                Button("Edit") {
                    editMode?.wrappedValue = .active
                }
            }
        }
    }
    
    private func moveItems(from offsets: IndexSet, to destination: Int) {
        items.move(fromOffsets: offsets, toOffset: destination)
    }
}

原因分析

自定义Edit按钮直接修改editMode的方式,和NavigationView的视图生命周期存在冲突,导致视图状态更新异常,进而丢失编辑控件的渲染状态。系统原生EditButton()内部已经处理了和NavigationView的状态同步逻辑,所以不会出现这个问题。

解决方案

方案1:使用系统原生EditButton()(推荐)

直接替换自定义按钮为系统提供的EditButton(),它会自动处理编辑状态的同步与视图更新:

import SwiftUI

struct ContentView: View {
    @State private var items = [1, 2, 3]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: \.self) {
                    Text("Item \($0)")
                }
                .onDelete {_ in }
                .onMove(perform: moveItems)
            }
            .toolbar {
                EditButton() // 使用系统原生编辑按钮
            }
        }
    }
    
    private func moveItems(from offsets: IndexSet, to destination: Int) {
        items.move(fromOffsets: offsets, toOffset: destination)
    }
}

方案2:iOS 16+使用NavigationStack替代NavigationView

如果需要保留自定义按钮,在iOS 16及以上版本可以用NavigationStack替代NavigationView,它的状态管理逻辑更稳定:

import SwiftUI

struct ContentView: View {
    @Environment(\.editMode) var editMode
    @State private var items = [1, 2, 3]
    
    var body: some View {
        NavigationStack { // 替换为NavigationStack
            List {
                ForEach(items, id: \.self) {
                    Text("Item \($0)")
                }
                .onDelete {_ in }
                .onMove(perform: moveItems)
            }
            .toolbar {
                Button(editMode?.wrappedValue == .active ? "Done" : "Edit") {
                    withAnimation {
                        editMode?.wrappedValue.toggle()
                    }
                }
            }
        }
    }
    
    private func moveItems(from offsets: IndexSet, to destination: Int) {
        items.move(fromOffsets: offsets, toOffset: destination)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:36:34