iOS 16.0中SwiftUI的.onMove函数移动功能异常
SwiftUI .onMove 拖动列表项消失且无法保存位置问题
问题现象:
触发列表项移动操作时,项会正常高亮,但拖动过程中该项莫名消失,松开后又回到初始位置。最低适配iOS 16.0,无论是否开启编辑模式,问题表现一致,未使用EditButton()。
复现代码:
import SwiftUI struct Animal: Identifiable { var id = UUID() var name: String } struct ListMove: View { @State var animals = [Animal(name: "Dog"), Animal(name: "Cat"), Animal(name: "Cow"), Animal(name: "Goat"), Animal(name: "Chicken")] var body: some View { List { ForEach(animals) { animal in Text(animal.name) } .onMove(perform: move) } } func move(from source: IndexSet, to destination: Int) { animals.move(fromOffsets: source, toOffset: destination) } } #Preview { ListMove() }
问题现象截图:
解决方案
iOS 16+ 的 List 使用 .onMove 时,必须处于编辑模式才能让移动操作真正生效并保存位置。之前的代码未绑定编辑状态,导致拖动仅为临时视觉反馈,不会触发数据变更。
修改后的代码:
import SwiftUI struct Animal: Identifiable { var id = UUID() var name: String } struct ListMove: View { @State var animals = [Animal(name: "Dog"), Animal(name: "Cat"), Animal(name: "Cow"), Animal(name: "Goat"), Animal(name: "Chicken")] // 管理编辑状态 @State private var isEditing = false var body: some View { List { ForEach(animals) { animal in Text(animal.name) } .onMove(perform: move) } // 将编辑状态绑定到List .environment(\.editMode, .constant(isEditing ? .active : .inactive)) // 用长按手势触发编辑模式切换(替代EditButton) .onLongPressGesture { isEditing.toggle() } } func move(from source: IndexSet, to destination: Int) { animals.move(fromOffsets: source, toOffset: destination) } } #Preview { ListMove() }
补充说明
- 如果不需要手动切换编辑状态,可直接设置
.environment(\.editMode, .constant(.active)),让List始终处于编辑模式,此时长按即可直接拖动列表项。 - 编辑状态绑定是触发
.onMove数据变更的必要条件,缺失会导致拖动操作无法持久化修改数组顺序。
内容的提问来源于stack exchange,提问作者Dennis Savchenko
相关产品推荐
相关产品推荐

