Loading object on NSItemProvider is delayed until drop exit

I have drag-and-drop functionality in the macOS app built with SwiftUI.

Since macOS 15 there is an issue with it, because as I found out, the completion block of loadObject method on NSItemProvider is not called until dropExited delegate method is called (see simplified code example below).

It causes very strange behavior in my app, for one of the most important features, and I am looking for a way to fix it as soon as possible.

Is anyone seeing the same issue?

I saw there was a bug with drag and drop on iOS 18, which seems to be fixed in 18.1. Anyone from Apple can say anything about this change in behaviour?

@Observable // Because it is injected via environment.
final class DragAndDropDelegate<T: Codable>: DropDelegate {
        
    func dropEntered(info: DropInfo) {
        
		    // Is called as expected.

        guard
            let itemProvider = info.itemProviders(for: [UTType.data]).first
        else { return }
        
        itemProvider.loadObject(ofClass: DraggableObject<T>.self) { [weak self] (object, error) in
			      // This is only called after dropExited delegate method is called !!!
			      // Before macOS 15.0 it is called quickly after the loadObject method invokation. 
            asyncOnMainThread {
                guard
                    let self,
                    let draggableObject = object as? DraggableObject<T>
                else { return }
                                
                self.onEnter?(draggableObject.object, info.location)
            }
        }
    }
    
    func dropExited(info: DropInfo) {
		    // Is called as expected.
    }
}
Answered by endore8 in 812715022

It seems like that was changed with macOS 15 because it worked perfectly fine before. Anyway, I found a fix.

The issue seems to be only because I have custom DraggableObject. I refactored to passing NSString instead, and encoding/decoding it by myself, and it works again.

Still means that passing custom object in NSItemProvider is broken.

The documentation indicates that you should use performDrop to load from the item provider.

enter and exit is only to indicate that a drag operation is targeting a view.

@J0hn is correct here. also have you looked into using Transferable items for drag and drop operations? The draggable(_:) modifier and dropDestination(for:action:isTargeted:) modifier is easier to adopt.

Adopting drag and drop using SwiftUI sample project should walk you through how to enable drag-and-drop interactions

Accepted Answer

It seems like that was changed with macOS 15 because it worked perfectly fine before. Anyway, I found a fix.

Loading object on NSItemProvider is delayed until drop exit
 
 
Q