SwiftUI:如何禁用长按拖动/滑动删除,修复EditButton无法触发编辑模式问题?
问题核心
你碰到的问题根源在于:
- 未正确绑定编辑状态,导致
EditButton点击后无法触发编辑UI(左侧红点、右侧拖动三线) - 未针对性禁用非编辑模式下的默认交互,长按拖动和滑动删除仍生效
完整解决方案代码
以下代码严格实现「仅通过EditButton进入编辑模式后,才能删除/重排序」的需求:
import SwiftUI // 数据源模型 class ListDataSource: ObservableObject { @Published var items = ["Item 1", "Item 2", "Item 3", "Item 4"] } struct RestrictedEditListView: View { @StateObject private var dataSource = ListDataSource() // 绑定环境中的编辑状态 @Environment(\.editMode) private var editMode var body: some View { NavigationStack { List { ForEach(dataSource.items, id: \.self) { item in Text(item) // 禁用非编辑模式下的滑动删除:用空的swipeActions覆盖默认交互 .swipeActions(edge: .trailing, allowsFullSwipe: false) {} // 禁用非编辑模式下的长按拖动:仅编辑模式返回有效拖动数据 .onDrag { guard editMode?.wrappedValue.isEditing == true else { return nil } return NSItemProvider(object: item as NSString) } } // 仅编辑模式下启用删除操作 .onDelete(perform: editMode?.wrappedValue.isEditing == true ? deleteItem : nil) // 仅编辑模式下启用重排序操作 .onMove(perform: editMode?.wrappedValue.isEditing == true ? moveItem : nil) } .navigationTitle("专属编辑模式") .toolbar { EditButton() } } } // 删除逻辑 private func deleteItem(at offsets: IndexSet) { dataSource.items.remove(atOffsets: offsets) } // 重排序逻辑 private func moveItem(from source: IndexSet, to destination: Int) { dataSource.items.move(fromOffsets: source, toOffset: destination) } }
关键实现说明
- 绑定编辑状态:通过
@Environment(\.editMode)获取当前编辑模式,作为所有交互开关的判断依据。 - 禁用滑动删除:给列表行添加空的
.swipeActions,覆盖系统默认的滑动删除交互,同时设置allowsFullSwipe: false防止误触。 - 禁用长按拖动:在
.onDrag回调中,仅当处于编辑模式时返回有效的拖动数据,非编辑模式返回nil,系统便不会触发长按拖动。 - 控制编辑操作生效时机:
onDelete和onMove仅在编辑模式下传入对应操作方法,非编辑时传nil,系统才会在编辑模式下显示红点和拖动三线。 - 导航容器依赖:确保
List被NavigationStack(iOS16+)或NavigationView包裹,因为EditButton需要放在toolbar中,而toolbar必须依附于导航容器。
内容的提问来源于stack exchange,提问作者Boyan Pavlov
相关产品推荐
相关产品推荐

