Enable and Disable SwiftUI List rows reordering on a specific row

⋅ 2 min read ⋅ SwiftUI List

Table of Contents

We can easily enable List row reordering in SwiftUI by attach .onMove modifier to the list content.

struct ReorderExample: View {
@State private var contacts = [...]

var body: some View {
NavigationView {
List {
ForEach(contacts, id: \.self) { contact in
Text(contact)
}
.onMove { from, to in
contacts.move(fromOffsets: from, toOffset: to)
}
}
.toolbar {
EditButton()
}
}

}
}

This will enable item reordering on every row. If you want to prevent some rows from moving, you can do that by using moveDisabled(_:) on that particular row.

onMove modifier enable reordering on all rows.
onMove modifier enable reordering on all rows.

You can easily support sarunw.com by checking out this sponsor.

Sponsor sarunw.com and reach thousands of iOS developers.

How to disable item reordering on a specific row

To disable item reordering on a particular row, you might want to add a new property in your data model to dictate that the item can't be moved.

In this case, I create a sticky flag in my model.

struct Contact: Identifiable {
let id = UUID()
let name: String
let sticky: Bool
}

Then mark the item you want to disable reordering by setting sticky to true.

@State private var contacts = [
Contact(name: "John", sticky: false),
Contact(name: "Alice", sticky: true),
Contact(name: "Bob", sticky: true),
Contact(name: "Foo", sticky: false),
Contact(name: "Bar", sticky: false)
]

Then inside each row, you use that sticky flag to set .moveDisabled(contact.sticky) modifier.

struct DisableMoveExample: View {
@State private var contacts = [
Contact3(name: "John", sticky: false),
Contact3(name: "Alice", sticky: true),
Contact3(name: "Bob", sticky: true),
Contact3(name: "Foo", sticky: false),
Contact3(name: "Bar", sticky: false)
]

var body: some View {
NavigationView {
List {
ForEach(contacts) { contact in
Text(contact.name)
.moveDisabled(contact.sticky)
}.onMove { from, to in
contacts.move(fromOffsets: from, toOffset: to)
}
}
.toolbar {
EditButton()
}
}

}
}

Run the app again, and the rows which have .moveDisabled set to true won't have the drag handler UI.

You can disable reordering on specific rows by adding the moveDisabled(true) modifier.
You can disable reordering on specific rows by adding the moveDisabled(true) modifier.

Read more article about SwiftUI, List, or see all available topic

Enjoy the read?

If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.

Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.

If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.

Become a patron Buy me a coffee Tweet Share
Previous
Unwrap Swift optional value in Switch case

Learn how to test for unwrapped optional values in a switch statement.

Next
Using SwiftUI in UIKit as UIViewController

We can use SwiftUI view in UIKit by wrapping it in UIViewController. Let's learn how to do it.

← Home