Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement drag and drop to 3rd party apps in SwiftUI on macOS

I've tried to Google for the answer but all I find are how to accept drop from other apps and drag and drop in a single app, also mostly iOS focus and not many macOS related resources.

I writing a macOS toolbar app that I'm trying to implement drag and drop for the image the app create programatically and only in memory as NSImage. To allow the image to be draggable, I've implemented the a DraggableImage struct to be used in place of the Image view in the SwiftUI view:

struct DraggableImage: View {
    let image: NSImage

    var body: some View {
        Image(nsImage: image)
            .resizable()
            .scaledToFit()
            .padding()
            .onDrag {
                guard let tiffRepresentation = image.tiffRepresentation,
                      let bitmapImage = NSBitmapImageRep(data: tiffRepresentation),
                      let bitmapRepresentation = bitmapImage.representation(using: .png, properties: [:]) else {

                    return NSItemProvider(item: image.tiffRepresentation as NSSecureCoding?, typeIdentifier: kUTTypeTIFF as String)
                }

                let provider = NSItemProvider(item: bitmapRepresentation as NSSecureCoding?,
                                              typeIdentifier: kUTTypePNG as String)

                provider.previewImageHandler = { (handler, _, _) -> Void in
                    handler?(bitmapRepresentation as NSSecureCoding?, nil)
                }

                return provider
            }
    }
}

The DraggableImage struct works as expected if I am dragging the image onto an app like TextEdit or Email app. See below:

Drag & Drop DraggableImage to TextEdit Document

However, I could not get the picture to be draggable onto anything file based apps like the Finder window. See below:

Drag & Drop DraggableImage to a Finder Window

Same thing dragging to the Desktop (which technically is a fullscreen Finder window):

Drag & Drop DraggableImage to The Desktop

What is missing in the implementation?

PS: The full demo project is hosted on GitHub for those interested in the implementation.

like image 725
WeyHan Ng Avatar asked Oct 20 '21 10:10

WeyHan Ng


1 Answers

You need to export file URL instead of Data, so this file can be copied by MacOS.

Basic example:

let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("dragExport.png")
try! bitmapRepresentation.write(to: url)

let provider = NSItemProvider(item: url as NSSecureCoding?, typeIdentifier: kUTTypeFileURL as String)
provider.suggestedName = url.lastPathComponent
like image 185
Philip Dukhov Avatar answered Oct 19 '22 10:10

Philip Dukhov