Search code examples
swiftuiswiftui-list

SwiftUI List on macOS: Enable Selection, double click and dragging


I have a simple List with using the new contextMenu(forSelectionType: ..., primaryAction: ) to enable a double click:

struct ContentView: View {
    
    var items = ["Item1", "Item2", "Item3"]
    
    @State private var selection: String? = nil
    
    var body: some View {
        List(selection: self.$selection) {
            ForEach(self.items, id: \.self) { item in
                Text(item)
            }
        }
        .contextMenu(forSelectionType: String.self) { items in
            Button("Test") {}
        } primaryAction: { items in
            print(items)
        }
    }
}

This works well.

But I also want to provide a drag option, so that I can drag out the selected items (actually in my use case I am displaying files and I want to enable the option to drag those files to the Finder or other apps). For my example I will just use the String:

struct ContentView: View {
    
    var items = ["Item1", "Item2", "Item3"]
    
    @State private var selection: String? = nil
    
    var body: some View {
        List(selection: self.$selection) {
            ForEach(self.items, id: \.self) { item in
                Text(item)
                    .draggable(item)
            }
        }
        .contextMenu(forSelectionType: String.self) { items in
            Button("Test") {}
        } primaryAction: { items in
            print(items)
        }
    }
}

After now adding the draggable-modifier, the selection of the item is not working anymore. The same is happening when using the older onDrag-modifier.

Does anyone has an idea how to provide selection and dragging?


Solution

  • Oh, I just found the solution here: https://developer.apple.com/forums/thread/664469 (I didn't saw this thread in my last search). So the solution will be:

    struct ContentView: View {
        
        var items = ["Item1", "Item2", "Item3"]
        
        @State private var selection: String? = nil
        
        var body: some View {
            List(selection: self.$selection) {
                ForEach(self.items, id: \.self) { item in
                    Text(item)
                        .itemProvider {
                            return NSItemProvider(object: item as NSString)
                        }
                }
            }
            .contextMenu(forSelectionType: String.self) { items in
                Button("Test") {}
            } primaryAction: { items in
                print(items)
            }
        }
    }