What Do You Get When You Drag and Drop a PNG File From Finder Into an NSTextView?
In short: Image file drag and drop does only produce file URLs, either with security scope-able bookmarks or plain file paths.
Dragging an image file from Finder onto an NSTextView
will trigger performDragOperation(_:)
. You get access to NSDraggingInfo
there and can inspect available content. Its draggingPasteboard
(shortened to pb
here) contains the following data when executed on macOS 12 Monterey:
Code | Value |
---|---|
pb.string(forType: .string) |
nil |
pb.string(forType: .URL) |
nil |
NSURL(from: pb) |
file:///.file/id=xyz12 3 |
pb.string(forType: .fileURL) |
file:///.file/id=xyz123 |
NSURL(from: pb) as URL? |
file:///path/to/a.png |
URL(string: pb.string( |
file:///path/to/a.png |
Note that the .URL
and .fileURL
pasteboard types were added in macOS 10.13. Before that, you had to use the NSURL.init(from:)
helper, the docs say. The table shows it still works.
Also pay attention to bridging NSURL
to Swift URL
: this changes the file URL or security scoped bookmark URL to an absolute file path. Accessing a resource with a security scope using these won’t work, I believe. Haven’t tested that yet.
When inspecting all available pasteboard types, you get these:
> pb.types?.map { $0.rawValue }
["public.file-url",
"CorePasteboardFlavorType 0x6675726C",
"dyn.ah62d4rv4gu8y6y4grf0gn5xbrzw1gydcr7u1e3cytf2gn",
"NSFilenamesPboardType",
"dyn.ah62d4rv4gu8yc6durvwwaznwmuuha2pxsvw0e55bsmwca7d3sbwu",
"Apple URL pasteboard type",
"com.apple.finder.node"])
I have no clue what the dyn.
-prefixed ones are supposed to be. "NSFilenamesPboardtype"
can be interesting, and "public.file-url"
reveals what the .fileURL
pasteboard type actually is under the hood. (You could maybe add a shim and read the file URL type even in macOS 10.12 and earlier that way – but I haven’t verified if that’s true or if dragging a file on macOS 10.12 does not actually set the "public.file-url"
pasteboard type.)
Also note that pb.availableType(from: [.string, .fileContents, .html, .png, .tiff])
will be nil
. You would need to use the newer .fileURL
type to get a non-nil result, even though NSURL.init(from:)
works.
This also shows that there’s no actual image associated witht he drag operation, which may or may not surprise you.
As a bonus, if you inspect the string values of all available types, formatted for readability, you get:
> pb.types?.map { pb.string(forType: $0) }
- public.file-url
file:///.file/id=xyz123
- CorePasteboardFlavorType 0x6675726C
file:///.file/id=xyz123
- dyn.ah62d4rv4gu8y6y4grf0gn5xbrzw1gydcr7u1e3cytf2gn
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>/path/to/a.png</string>
</array>
</plist>
- NSFilenamesPboardType
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>/path/to/a.png</string>
</array>
</plist>
- dyn.ah62d4rv4gu8yc6durvwwaznwmuuha2pxsvw0e55bsmwca7d3sbwu
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>file:///.file/id=xyz123</string>
<string></string>
</array>
</plist>
- Apple URL pasteboard type
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>file:///.file/id=xyz123</string>
<string></string>
</array>
</plist>
- com.apple.finder.node
file:///.file/id=xyz123