I have had dragging and dropping working for Mail working for a while now. That was until I upgraded to OSX 10.13.
Here is my code:
class DropView: NSView
{
var filePath: String?
required init?(coder: NSCoder) {
super.init(coder: coder)
self.wantsLayer = true
self.layer?.backgroundColor = NSColor.red.cgColor
registerForDraggedTypes([NSPasteboard.PasteboardType
.fileNameType(forPathExtension: ".eml"), NSPasteboard.PasteboardType.filePromise])
}
override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
if true
{
self.layer?.backgroundColor = NSColor.blue.cgColor
return .copy
}
}
override func draggingExited(_ sender: NSDraggingInfo?)
{
self.layer?.backgroundColor = NSColor.red.cgColor
}
override func draggingEnded(_ sender: NSDraggingInfo)
{
self.layer?.backgroundColor = NSColor.gray.cgColor
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool
{
let pasteboard: NSPasteboard = sender.draggingPasteboard()
let filePromises = pasteboard.readObjects(forClasses: [NSFilePromiseReceiver.self], options: nil) as? [NSFilePromiseReceiver]
let folderPath = NSHomeDirectory()+"/Drop Stuff/"
if (!FileManager.default.fileExists(atPath: folderPath))
{
do
{
try FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil)
}
catch
{
print ("error")
}
}
let folderURL = NSURL(fileURLWithPath: folderPath)
let f = sender.namesOfPromisedFilesDropped(atDestination: folderURL as URL)
print (f!)
print ("Copied to \(folderPath)")
return true
}
}
The problem is that namesOfPromisedFilesDropped is returning the name of the parent folder not the name of the file as it did on previous version of the OS.
The compiler warns that namesOfPromisedFilesDropped is deprecated. Good job Apple for not providing any documentation on the new stuff. Thanks to StackOverflow I managed to piece this together which works using the new APIs, but still exhibits the same problem as above.
class DropView2: NSView
{
var filePath: String?
required init?(coder: NSCoder) {
super.init(coder: coder)
self.wantsLayer = true
self.layer?.backgroundColor = NSColor.red.cgColor
registerForDraggedTypes([NSPasteboard.PasteboardType
.fileNameType(forPathExtension: ".eml"), NSPasteboard.PasteboardType.filePromise])
}
override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
if true
{
self.layer?.backgroundColor = NSColor.blue.cgColor
return .copy
}
}
override func draggingExited(_ sender: NSDraggingInfo?)
{
self.layer?.backgroundColor = NSColor.red.cgColor
}
override func draggingEnded(_ sender: NSDraggingInfo)
{
self.layer?.backgroundColor = NSColor.gray.cgColor
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool
{
let pasteboard: NSPasteboard = sender.draggingPasteboard()
guard let filePromises = pasteboard.readObjects(forClasses: [NSFilePromiseReceiver.self], options: nil) as? [NSFilePromiseReceiver] else {
return false
}
print ("Files dropped")
var files = [URL]()
let filePromiseGroup = DispatchGroup()
let operationQueue = OperationQueue()
let destURL = URL(fileURLWithPath: "/Users/andrew/Temporary", isDirectory: true)
print ("Destination URL: \(destURL)")
filePromises.forEach ({ filePromiseReceiver in
print (filePromiseReceiver)
filePromiseGroup.enter()
filePromiseReceiver.receivePromisedFiles(atDestination: destURL,
options: [:],
operationQueue: operationQueue,
reader:
{ (url, error) in
print ("Received URL: \(url)")
if let error = error
{
print ("Error: \(error)")
}
else
{
files.append(url)
}
print (filePromiseReceiver.fileNames, filePromiseReceiver.fileTypes)
filePromiseGroup.leave()
})
})
filePromiseGroup.notify(queue: DispatchQueue.main,
execute:
{
print ("Files: \(files)")
print ("Done")
})
return true
}
}
I'm using 10.13.2. Am I doing something wrong or is this a bug?
It's driving me nuts.