NSDraggingDestination 是 macOS AppKit 框架中的协议,用于实现拖放目标(拖入)行为。
如果希望视图、窗口或控件能够作为 拖拽目标,例如接收文件、图片、文本、自定义数据。
就要让该对象(通常是 NSView 或 NSWindow)实现 NSDraggingDestination 协议。
基本功能
当用户拖动某个项目(如文件、图片、文本)到mac应用上时,系统会:
1、向视图发送 NSDraggingDestination 协议方法
2、可以根据拖入类型决定:
是否接受。
拖入时显示什么反馈(边框高亮等)。
拖放到哪里触发什么操作。
常用方法
1、draggingEntered(_:):拖入区域时触发,可返回接受类型(如 .copy)。
2、draggingUpdated(_:):拖动过程中不断触发,用于动态反馈。
3、draggingExited(_:):拖出区域时触发。
4、prepareForDragOperation(_:):放开前准备,返回是否接受。
5、performDragOperation(_:):实际执行放入动作。
6、concludeDragOperation(_:):拖拽完成后调用(动画完成)。
使用场景
1、通过draggingEntered返回 .copy 让系统显示绿色加号光标。
也可以在NSView中设置:
override func draw(_ dirtyRect: NSRect) {
if isHighlighting {
NSColor.selectedControlColor.set()
__NSRectFillUsingOperation(dirtyRect, .sourceOver)
}
}

2、拖入图片到视图中
registerForDraggedTypes([.tiff])
func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
if let data = sender.draggingPasteboard.data(forType: .tiff),
let image = NSImage(data: data) {
self.image = image
self.needsDisplay = true
return true
}
return false
}
3、让视图实现协议
class DropReceivingView: NSView, NSDraggingDestination {
override func awakeFromNib() {
super.awakeFromNib()
registerForDraggedTypes([.fileURL, .string])
}
func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
return .copy
}
func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
let pasteboard = sender.draggingPasteboard
if let urls = pasteboard.readObjects(forClasses: [NSURL.self], options: nil) as? [URL] {
for url in urls {
print("拖入文件:\(url.path)")
}
return true
}
return false
}
}
4、注册支持的类型
registerForDraggedTypes([
.fileURL, // 拖入文件
.string, // 拖入纯文本
.tiff, // 拖入图片
NSPasteboard.PasteboardType("public.jpeg") // 支持其他 UTI
])
总结
当需要实现拖入文件、图片等数据到窗口时,可以使用NSDraggingDestination,如果是App内部控件之间的拖动,需要使用NSDraggingSource。
SwiftUI没有原生完整拖动支持,在macOS13之前的版本,可以使用NSViewRepresentable包装NSView + NSDraggingDestination。
通常配合辅助类型NSPasteboard、NSDraggingInfo(拖拽上下文)和NSDragOperation(拖入操作类型 .copy,.link,.move)使用。