SwiftUI拖动排序onMove
SwiftUI拖动排序onMove

SwiftUI拖动排序onMove

SwiftUI的onMove是“拖动排序列表项”的修饰器,仅限于在List中使用,用于响应用户拖动列表项改变顺序的动作。

基本用法

List {
    ForEach(items, id: \.self) { item in
        Text(item)
    }
    .onMove { indices, newOffset in
        items.move(fromOffsets: indices, toOffset: newOffset)
    }
}
.toolbar { EditButton() }

onMove的函数类型是(IndexSet, Int) -> Void:

indices: IndexSet —— 被移动项的原始索引集合(可以包含多个索引)。

newOffset: Int —— 要插入到的目标索引(插入点的下标)。

也可以使用另一种用法:

List {
    ForEach(banks) { bank in
        Text(bank.name)
    }
    .onMove(perform: move)
}
.toolbar { EditButton() }

func move(from source: IndexSet, to destination: Int) {
	...
}

使用示例

1、SwiftData中实现排序的功能

SwiftData数据通过@Query实现SwiftUI的查询和排序,需要借助排序字段实现排序:

// 1、新增排序字段
@Model
class PiggyBank {
    var sortOrder: Int = 0  // 新增排序字段
}

// 2、修改 Query排序:
@Query(sort: [
    SortDescriptor(\PiggyBank.sortOrder),
    SortDescriptor(\PiggyBank.creationDate, order: .reverse)
])
var allPiggyBank: [PiggyBank]

// 3、onMove实现排序:
.onMove { indices, newOffset in
    var banks = allPiggyBank
    banks.move(fromOffsets: indices, toOffset: newOffset)
    
    // 更新所有 sortOrder
    for (index, bank) in banks.enumerated() {
        bank.sortOrder = index
    }
    try? context.save()
}

onMove移动列表项后,复制一个临时数组存储当前的所有存钱罐列表,move方法移动对应元素,之后根据临时数组的排序,修改sortOrder排序字段,从而实现修改SwiftData排序的功能。

注意:Query查询顺序不要出错,如果显示反向排序,和for-in的排序正向排序存在不一致,显示排序就会出现问题。

注意事项

1、Xcode Preview环境中无法触发onMove方法

需要在模拟器或真机中使用,Preview环境中无法触发onMove方法,拖动时列表视图可能无法正常显示。

2、ForEach的id如果不稳定,可能导致移动后UI闪烁或数据错位。

总结

onMove 是 SwiftUI 提供的用于响应用户在列表中拖动并重排行的事件回调。它本身不修改数据,需要开发者手动处理移动的索引和排序。

通常配合ForEach / List使用,还可以配合onDelete进行删除操作,也可以在编辑模式EditButton() 启用排序功能。

.toolbar { EditButton() } // 显示系统的“编辑”按钮

// 或者强制编辑模式:
.environment(\.editMode, .constant(.active))

相关文章

1、SwiftUI滚动内容ScrollView:https://fangjunyu.com/2024/12/20/swiftui%e6%bb%9a%e5%8a%a8%e5%86%85%e5%ae%b9scrollview/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注