The core of file drag is DragDestinationView. This method will detect whether the target can be dragged type, drag file information, image will return image, Color will return Color, docx, PPT, zip and other return path (URL).

import Cocoa import CocoaExpand @objc protocol DragDestinationViewDelegate: NSObjectProtocol { @objc optional func processImage(_ image: NSImage, pasteBoard: NSPasteboard) @objc optional func process(_ obj: Any, pasteBoard: NSPasteboard)} @available(macOS 10.13, *) class DragDestinationView: NSView {var delegate: DragDestinationViewDelegate? Var supportedTypes: [NSPasteboard.PasteboardType] = [.tiff, .color, .string, .fileURL, .html] {willSet {self. RegisterForDraggedTypes (newValue)}} / / / support into subtypes var acceptableUTITypes: [NSPasteboard.ReadingOptionKey : Any] { let types = [NSImage.imageTypes, NSString.readableTypeIdentifiersForItemProvider, NSURL.readableTypeIdentifiersForItemProvider].flatMap { $0 } return [NSPasteboard.ReadingOptionKey.urlReadingContentsConformToTypes : types] } var isReceivingDrag = false { didSet { needsDisplay = true } } // MARK: -lifecycle convenience init(types: [NSPasteboard.PasteboardType]) { self.init() self.registerForDraggedTypes(types) } // MARK: -drag override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { return .copy } override func draggingExited(_ sender: NSDraggingInfo?) { isReceivingDrag = false } override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool {return true} // // func performDragOperation(_ sender: NSDraggingInfo) -> Bool { // // isReceivingDrag = false // let pasteBoard = sender.draggingPasteboard // guard let image  = NSImage(pasteboard: pasteBoard) else { // return false // } // delegate? .processImage? (image, pasteBoard: pasteBoard) // return true // } override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { isReceivingDrag = false let pasteBoard = sender.draggingPasteboard let classArray: [AnyClass] = [NSImage.self, NSColor.self, NSString.self, NSURL.self] return pasteBoard.readObjects(forClasses: classArray, options: acceptableUTITypes) { (obj) in if let value = obj as? NSImage { self.delegate?.processImage?(value, pasteBoard: pasteBoard) } else { self.delegate?.process?(obj, pasteBoard: pasteBoard) } } } override func concludeDragOperation(_ sender: NSDraggingInfo?) { } }Copy the code
@available(OSX 10.13, *) var propertyList: [Any]? { if let board = self.propertyList(forType: NSPasteboard.PasteboardType(rawValue: "NSFilenamesPboardType")) as? [String] { print("FILE: \(board)") return board } if let board = self.propertyList(forType: .URL) as? [URL] { print("URL: \(board)") return board } if let board = self.propertyList(forType: .string) as? [String] { print("STRING: \(board)") return board } if let board = self.propertyList(forType: .html) as? [String] { print("HTML: \(board)") return board} return nil} @available(OSX 10.13, *) var draggedFileURL: NSURL? { if let property = propertyList? .first as? String { print(property) return NSURL(fileURLWithPath: /// Parse the information that can be dragged to the target view while options limits the type of child elements that can be dragged (nil means no type) func readObjects(forClasses classArray: [AnyClass] = [NSImage.self, NSColor.self, NSString.self, NSURL.self], options: [NSPasteboard.ReadingOptionKey : Any]? = nil, handler: ((Any)->Void)? = nil) -> Bool { guard let pasteboardObjects = readObjects(forClasses: classArray, options: options), pasteboardObjects.count > 0 else { return false } pasteboardObjects.forEach { (obj) in switch obj { case let value as NSImage: print(#function, #line, "NSImage", value) handler? (value) case let value as NSString: print(#function, #line, "NSString", value) handler? (value) case let value as NSColor: print(#function, #line, "NSColor", value) handler? (value) case let value as URL: print(#function, #line, "URL", value.absoluteString.removingPercentEncoding ?? "") if let image = NSImage(contentsOfFile: value.path) { print(#function, #line, image) handler? (image) } else { handler? (value) } default: print(#function, #line, obj) handler? (obj) break } } return true } }Copy the code