Library / Drag, swipe & scroll

List reorder ticks

Dragging a row through a list: one tick every time it displaces a neighbor, plus lift and settle haptics.

0ms 130ms 260ms 390ms 520ms
Feel
Soft lift, a small tick per position change (like passing over ridges), rigid settle at the end.
APIs
UISelectionFeedbackGeneratorUIImpactFeedbackGeneratoronMove
Minimum OS
iOS 10+
Raw .md
SwiftUI (iOS 17+)
import SwiftUI

struct ReorderableList: View {
    @State private var items = ["Inbox", "Today", "Upcoming", "Someday"]
    @State private var moves = 0

    var body: some View {
        List {
            ForEach(items, id: \.self) { Text($0) }
                .onMove { from, to in
                    items.move(fromOffsets: from, toOffset: to)
                    moves += 1
                }
        }
        .environment(\.editMode, .constant(.active))
        // One tick per completed move
        .sensoryFeedback(.selection, trigger: moves)
    }
}
UIKit (per-displacement ticks)
// UITableView drag & drop: tick each time the target row changes.
final class ReorderController: UITableViewController {
    private let tick = UISelectionFeedbackGenerator()
    private let settle = UIImpactFeedbackGenerator(style: .rigid)

    override func tableView(_ tableView: UITableView,
        targetIndexPathForMoveFromRowAt source: IndexPath,
        toProposedIndexPath proposed: IndexPath) -> IndexPath {
        if source != proposed {
            tick.selectionChanged()  // passed over a neighbor
            tick.prepare()
        }
        return proposed
    }

    override func tableView(_ tableView: UITableView,
        moveRowAt source: IndexPath, to destination: IndexPath) {
        // update data source ...
        settle.impactOccurred(intensity: 0.8) // row lands
    }
}
Copied