iOS15下SwiftUI的editMode.onDelete与自定义swipeActions共存问题
解决方案
根因说明
SwiftUI 自 iOS 15 引入swipeActions后,只要为列表行添加了自定义滑动操作,系统就会默认接管行的所有滑动手势响应,原生onDelete提供的左滑删除手势会被自动覆盖,属于框架的设计行为。
方案1:iOS 15+ 适配(保留原生editMode与swipeActions)
无需放弃原有能力,只需将删除操作也显式声明为trailing侧的自定义滑动操作,同时保留onDelete、onMove以支持编辑模式下的批量操作:
import SwiftUI import PlaygroundSupport struct SomeList: Identifiable { let id: UUID = UUID() var name: String } struct ContentView: View { @State private var editMode = EditMode.inactive @State private var someList: [SomeList] = [ SomeList(name: "row1"), SomeList(name: "row2"), SomeList(name: "row3") ] var body: some View { NavigationView { List { // 改为带索引的遍历,方便单条滑动删除时定位元素 ForEach(Array(someList.enumerated()), id: \.element.id) { index, someElement in Text(someElement.name) // leading侧右滑编辑 .swipeActions(edge: .leading) { Button("Edit") { // 你的编辑逻辑 } .tint(.blue) } // trailing侧左滑删除 .swipeActions(edge: .trailing) { Button("Delete", role: .destructive) { someList.remove(at: index) } } } // 保留onDelete、onMove,用于编辑模式下的批量操作 .onDelete { indexSet in someList.remove(atOffsets: indexSet) } .onMove { source, destination in someList.move(fromOffsets: source, toOffset: destination) } } .toolbar { ToolbarItem(placement: .navigationBarLeading) { EditButton() } } .environment(\.editMode, $editMode) } } } PlaygroundPage.current.setLiveView(ContentView())
该方案实现效果完全匹配需求:
- 非编辑模式下:右滑出编辑按钮,左滑出删除按钮
- 点击EditButton进入编辑模式后:依然支持批量选中删除、行拖动排序
方案2:兼容iOS 13+ 低版本适配
如果需要支持iOS15以下系统,放弃swipeActions改用自定义实现即可:
- 用
DragGesture监听列表行的水平偏移,偏移达到阈值后显示对应操作按钮,松手后自动归位/触发操作 - 原生
editMode的onDelete、onMove能力可以完全保留,不受自定义手势影响 - 也可以封装UIKit的
UITableViewRowAction实现滑动操作,稳定性更优。
内容的提问来源于stack exchange,提问作者AdamSwift
相关产品推荐
相关产品推荐

