SwiftUI ForEach .onInsert not called for outside drags?

Hello, I'm trying to accept drags from outside my app to create a new row in a list.

I've observed .onInsert not getting called in this scenario and I'm curious if it's 100% not possible, or if there's an obscure view modifier that I am missing.

Thank you.

struct ContentView: View {
    @State var data = ["One", "Two", "Three"]
    
    var body: some View {
        HStack {
            List {
                ForEach(data, id: \.self) { item in
                    Text(item)
                }
                .onMove(perform: { indices, newOffset in
                    data.move(fromOffsets: indices, toOffset: newOffset)
                })
                .onInsert(of: [UTType.plainText], perform: { index, items in
                    // WORKS
                    data.insert("new", at: index)
                })
                .onInsert(of: [UTType.data], perform: { index, items in
                    // Never called
                    data.insert("OUTSIDE", at: index)
                })
            }
            
            Text("DragMe")
                .onDrag {
                    return NSItemProvider(item: "DragMe" as NSString, typeIdentifier: UTType.plainText.identifier)
                }
        }
    }
}

I'm seeing the same issue and finding older samples online that reportedly worked. Is this a regression?

I have confirmed that this is indeed broken and filed an Apple Feedback bug for it on macOS 14.5. It is partially fixed in the latest 15 RC but does not work if you are inserting between two Foreach's in the same List. Move does work correctly in that case

First of all, thanks for this, I've been looking for good sample code that showed how to implement NSItemProvider for drag/drop, and this helped.

  • It looks like only the first onInsert takes effect, I've seen this with other view modifiers like alert()

  • In your code, if I comment out the first onInsert viewModifier, the second one works, and it seems like I can drag pretty much anything into it, including random photos from finder, etc...

If you want some code that does one thing on plain text, and then another thing on every other kind of data, check this out

  • If you drag something from "Drag Plaintext", it will print "inserting plain text"
  • If you drag something from "Drag Data" (or drag something from finder/etc), it will print "inserting data"
import SwiftUI
import UniformTypeIdentifiers

var insertedItemCount = 0

struct ContentView: View {
    @State var data = ["One", "Two", "Three"]
    
    var body: some View {
        HStack {
            List {
                ForEach(data, id: \.self) { item in
                    Text(item)
                }
                .onMove(perform: { indices, newOffset in
                    data.move(fromOffsets: indices, toOffset: newOffset)
                })
                
                .onInsert(of: [UTType.data, UTType.plainText], perform: { index, items in
                    
                    for item in items {
                        if item.hasRepresentationConforming(toTypeIdentifier: UTType.plainText.identifier) {
                            print("Inserting plain text")
                            data.insert("Text: \(insertedItemCount)", at: index)
                        }
                        else if item.hasRepresentationConforming(toTypeIdentifier: UTType.data.identifier){
                            print("Inserting data")
                            data.insert("Data: \(insertedItemCount)", at: index)
                        }
                        else {
                            // I'm not sure when this would happen, even folders and weird file types are still "data"
                            print("Got something weird that isn't data or plain text")
                        }

                        insertedItemCount += 1
                    }
                })
            }
            
            Text("Drag Plaintext")
                .onDrag {
                    return NSItemProvider(item: "DragMe" as NSString, typeIdentifier: UTType.plainText.identifier)
                }
            Text("Drag Data")
                .onDrag {
                    return NSItemProvider(item: "DragMe" as NSString, typeIdentifier: UTType.data.identifier)
                }
        }
    }
}
#Preview {
    ContentView()
}

Hope that helps

SwiftUI ForEach .onInsert not called for outside drags?
 
 
Q