Moving List Items Using Drag and Drop in SwiftUI Mac Apps

Mac apps usually use drag and drop to rearrange items in a list. You search for how to move list items in SwiftUI, and you find a bunch of examples for iOS that use the .onMove modifier. But when you start to type .onMove in your Mac list, Xcode’s autocomplete shows only an .onMoveCommand modifier. If you try to use .onMove directly on a list in a Mac app, you’ll get a compiler error.

SwiftUI has an .onMoveCommand modifier to move items in a list in a SwiftUI Mac app, but it works with the keyboard, not with drag and drop. How do you use drag and drop to move items in a SwiftUI list in a Mac app?

.onMove Requires ForEach on Mac

The .onMove modifier is the modifier to use to move list items using drag and drop in SwiftUI Mac apps. But you must place a ForEach statement inside the list to enable .onMove. The ForEach statement takes two arguments: the array of items you’re showing in the list and an ID that uniquely identifies each list item.

Apply the .onMove modifier to the ForEach block. The .onMove modifier’s closure takes two arguments: the indices for the list items being moved and the drop destination. Call the array’s move method to reorder the list items.

The following code creates a list of a book’s chapters that you can rearrange using drag and drop:

// The chapter has an id property that uniquely identifies it.
List {
  ForEach($book.chapters, id: \.id) { $chapter in
    TextField("", text: $chapter.title)
  }
  .onMove { indices, destination in
    book.chapters.move(fromOffsets: indices, 
      toOffset: destination)
	}
}

Get the Swift Dev Journal Newsletter

Subscribe and get exclusive articles, a free guide on moving from tutorials to making your first app, notices of sales on books, and anything I decide to add in the future.

    We won't send you spam. Unsubscribe at any time.