Search code examples
swiftmacosswiftuinsitemprovider

NSItemProvider[URL] - how to COPY with drag&Drop instead of MOVE?


I have implemented function that returns NSItemProvider

func dragOutsideWnd(url: URL?) -> NSItemProvider {
    if let url = url {
        TheApp.appDelegate.hideMainWnd()
        
        let provider = NSItemProvider(item: url as NSSecureCoding?, typeIdentifier: UTType.fileURL.identifier as String)
        
        provider.suggestedName = url.lastPathComponent
        //provider.copy()// This doesn't work :)
        
        //DispatchQueue.main.async {
        //    TheApp.appDelegate.hideMainWnd()
        //}
        
        return provider
    }
    
    return NSItemProvider()
}

and I have use it this way:

.onDrag {
   return dragOutsideWnd(url: itm.url)
}

This drag&drop action performs file MOVE action to any place of FINDER/HDD.

But how to perform COPY action?


Solution

  • Remember Drag&Drop is actually implemented with NSPasteboard.

    I have written an example for you: GitHub

    enter image description here

    Now the key to your questions:

    To control dragging behavior(your window is the source):

    Draggable objects conform to the NSDraggingSource protocol, so check the first method of the protocol:

    @MainActor func draggingSession(
        _ session: NSDraggingSession,
        sourceOperationMaskFor context: NSDraggingContext
    ) -> NSDragOperation
    

    As the method docsuggests, return different NSDragOperation in this delegation method. That includes: "Copy","Move", "Link", etc.

    To control dropping behavior(your window is the destination):

    NSView that accepts drop conforms to the NSDraggingDestination protocol, so you need to override the draggingEntered(_:) method by adding this code inside the DestinationView class implementation:

    override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation 
    {
       var allow = true
       //.copy .move, see more options in NSDragOperation, up to you.
       return allow ? .copy : NSDragOperation() 
    }
    

    More info form Apple's Documentation

    For swiftUI, a simple show case SwiftUI Showcase

    Further Reading: RayWenderlich.com has a detailed tutorial Drag and Drop Tutorial for macOS tutorial for you(needs a little swift upgrade).