Drag and drop in list with SwiftUI

Asked on 08/03/2024

1 search

To implement drag and drop in a list with SwiftUI, you can use the onDrag and onDrop modifiers. These modifiers help you create accessible drag and drop experiences. Here are some relevant details from the WWDC sessions:

  1. Drag and Drop Accessibility:

    • In the session Catch up on accessibility in SwiftUI, it is mentioned that drag and drop are supported with accessibility technologies like VoiceOver and Voice Control. You can use the onDrag and onDrop modifiers to enhance the experience for your app. For example, you can define multiple drop points on a single view using a custom drop delegate.
  2. List Customization:

    • In the session SwiftUI essentials, it is explained how lists can be customized through view modifiers. This includes adding swipe actions to each row, which can be combined with drag and drop functionality to create a more interactive list.
  3. Drop Destinations on Tabs:

    • In the session Elevate your tab and sidebar experience in iPadOS, it is discussed how tabs can be drop destinations. This allows for direct additions into tabs in the sidebar or tab bar through drag and drop, using the dropDestination modifier.

Here is a simple example of how you might implement drag and drop in a SwiftUI list:

struct DraggableItem: Identifiable {
    let id = UUID()
    let name: String
}

struct ContentView: View {
    @State private var items = [
        DraggableItem(name: "Item 1"),
        DraggableItem(name: "Item 2"),
        DraggableItem(name: "Item 3")
    ]
    
    var body: some View {
        List {
            ForEach(items) { item in
                Text(item.name)
                    .onDrag {
                        NSItemProvider(object: item.name as NSString)
                    }
                    .onDrop(of: [UTType.text], delegate: DropViewDelegate(item: item, items: $items))
            }
        }
    }
}

struct DropViewDelegate: DropDelegate {
    let item: DraggableItem
    @Binding var items: [DraggableItem]
    
    func performDrop(info: DropInfo) -> Bool {
        // Handle the drop logic here
        return true
    }
}

This example demonstrates how to make list items draggable and how to handle drop actions using a custom drop delegate. For more detailed information, you can refer to the sessions mentioned above.