Can sections be moved/reordered within list (via onMove-style dragging)?

Consider the following example of a List view containing sections of rows.

import SwiftUI
struct ListSectionView: View {
@State private var sectionHeaders = ["section1", "section2", "section3"]
var body: some View {
List {
ForEach(sectionHeaders, id: \.self) { sectionHeader in
Section(header: Text(sectionHeader)) {
Text("1")
Text("2")
Text("3")
}
}
.onMove { indices, newOffset in
// ...
}
}
}
}

I would like to reorder the sections within the list by dragging the respective section header to its new position in the list - similar to moving individual rows via onMove-dragging but with the sections instead of the rows.

The above approach does not work. It "activates" moving the rows and then the .onMove code acts on those. The sections themselves are not moved.

How can I move/reorder the sections within the list?

Thanks.

onMove is great when you want to re-order items in a list. To move the sections, you'll need to use the draggable and dropDestination(for:action:isTargeted:) modifiers. You can checkout Adopting drag and drop using SwiftUI sample project and Making a view into a drag source to learn more about Drag and Drop in SwiftUI.

struct SectionItem: Identifiable, Equatable, Codable {
var id = UUID()
var title: String
var rows: [RowItem]
}
struct RowItem: Identifiable, Codable, Equatable {
var id = UUID()
var text: String
}
extension SectionItem: Transferable {
static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(contentType: .data)
}
}
struct ListSectionView: View {
@State private var sections: [SectionItem] = [
SectionItem(title: "section1", rows: [
RowItem(text: "section1: 1"),
RowItem(text: "section1: 2"),
RowItem(text: "section1: 3")
]),
SectionItem(title: "section2", rows: [
RowItem(text: "section2: 1"),
RowItem(text: "section2: 2"),
RowItem(text: "section2: 3")
]),
SectionItem(title: "section3", rows: [
RowItem(text: "section3: 1"),
RowItem(text: "section3: 2"),
RowItem(text: "section3: 3")
])
]
var body: some View {
List {
ForEach(sections) { section in
Section(header:
Text(section.title)
.padding(.vertical, 5)
.contentShape(Rectangle())
.draggable(section)
) {
ForEach(section.rows) { row in
Text(row.text)
}
}
.dropDestination(for: SectionItem.self) { droppedItems, location in
guard let droppedItem = droppedItems.first,
let sourceIndex = sections.firstIndex(where: { $0.id == droppedItem.id }),
let destinationIndex = sections.firstIndex(where: { $0.id == section.id })
else {
return false
}
if sourceIndex != destinationIndex {
withAnimation {
let movedSection = sections.remove(at: sourceIndex)
sections.insert(movedSection, at: destinationIndex > sourceIndex ? destinationIndex : destinationIndex)
}
}
return true
}
}
}
}
}
Can sections be moved/reordered within list (via onMove-style dragging)?
 
 
Q