一、概述
如果应用中有对文本、文件、图片的移动、复制操作,Drag & Drop 是非常高效而直观的。
二、相关类与协议
Drag 相关类和协议位于 AppKit 中
- NSDraggingImageComponent
- NSDraggingItem
- NSDraggingSession
protocols
- NSDraggingInfo
- NSDraggingDestination
- NSDraggingSource
- NSSpringLoadingDestination
可拖拽的对象,需要遵守 NSDraggingSource 协议;
可作为拖拽目标的对象,遵守 NSDraggingDestination 协议。
AppKit 隐藏了鼠标追踪和展示拖拽视图的所有细节。
NSWindow 和 NSView 对象可以成为drags 的资源地和目的地。
三、使用
让我们直接进入使用,上手后再进一步了解它吧,这里介绍一个简单的使用 NSView 作为接收端的样例吧。参考 demo:
https://github.com/huangqizai/Mac_DragDrop
1、构建视图
创建 OneView 继承自 NSView ;
在OneView 上添加一个 NSImageView 来获取拖拽的效果。
@interface OneView : NSView
@end
@interface OneView (){
BOOL isReceivingDrag; //是否正在拖拽操作
}
@property (nonatomic, strong) NSImageView *iconView;
@end
@implementation OneView
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
if (isReceivingDrag) {
[[NSColor redColor] set]; //进入时,边框颜色变红
}else{
[[NSColor blueColor] set]; //正常状态下,边框颜色为蓝
}
NSBezierPath *path = [NSBezierPath bezierPathWithRect:dirtyRect];
path.lineWidth = 2;
[path stroke];
}
-(instancetype)initWithFrame:(NSRect)frameRect{
self = [super initWithFrame:frameRect];
self.wantsLayer = YES;
self.layer.backgroundColor = [NSColor cyanColor].CGColor;
self.iconView = [[NSImageView alloc]initWithFrame:NSMakeRect(5, 5, 470, 350)];
[self addSubview:self.iconView];
self.iconView.wantsLayer = YES;
self.iconView.layer.backgroundColor = [NSColor yellowColor].CGColor;
[self registerForDraggedTypes:@[NSPasteboardTypeFileURL, NSPasteboardTypePNG]]; // 注册拖拽类型
return self;
}
点击 NSView 进入头文件,会发现它已经遵守 NSDraggingDestination 协议,所以这里我们不需要再次添加协议。
2、添加代理方法 NSDraggingDestination
#pragma mark - NSDraggingDestination
// 拖拽结束后调用(无论是否拖拽成功)
-(void)draggingEnded:(id<NSDraggingInfo>)sender{
NSLog(@"-- draggingEnded");
isReceivingDrag = NO;
[self setNeedsDisplay:YES];
}
// 拖进来但没放下时调用
-(void)draggingExited:(id<NSDraggingInfo>)sender{
NSLog(@"-- draggingExited");
}
/*
拖动数据进入来时调用
可以在这里判断数据是什么类型
*/
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender{
isReceivingDrag = YES;
[self setNeedsDisplay:YES];
NSPasteboard *pb = [sender draggingPasteboard];
NSLog(@"-- draggingEntered \n pboard types : %@",[pb types]);
if ([[pb types] containsObject:NSPasteboardTypeFileURL]) {
return NSDragOperationCopy;
}
return NSDragOperationNone;
}
/*
松开鼠标时会触发,可以在这里处理接收到的数据
*/
-(BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender{
// 1)、获取拖动数据中的粘贴板
NSPasteboard *pb = [sender draggingPasteboard];
// 2)、从粘贴板中提取我们想要的NSFilenamesPboardType数据,这里获取到的是一个文件链接的数组,里面保存的是所有拖动进来的文件地址,如果你只想处理一个文件,那么只需要从数组中提取一个路径就可以了。
NSArray *list = [pb propertyListForType:NSFilenamesPboardType];
if (list.count > 0) {
NSString *path = list.firstObject;
self.iconView.image = [[NSImage alloc] initWithContentsOfFile:path];
}
NSLog(@"list : %@",list);
return YES;
}
3、查看运行效果
应用运行起来的初始化效果
拖拽图片时(边框变红)
放下后
四、功能设计
关于功能的设计,最好阅读下面文档,来合理应用在不同场合。
https://developer.apple.com/design/human-interface-guidelines/macos/user-interaction/drag-and-drop/
在规划 Drag & Drop 功能的时候,最好也考虑一下几点:
- 有其他替代的功能,能实现 Drag & Drop 同样的效果;
- 让 Drag & Drop 操作可逆,以防止用户误操作;
- Drag & Drop 可以产生移动或复制的效果。一般而言,在同一个应用、文档中(即使是不同的窗口),移动更有意义。在不同的应用、文档或磁盘之间,复制更有意义。
对于拖拽
- 最好用户选中文件就可以拖拽到目的地。不要再这个过程中做选择、中断。
- 允许用户从非激活窗口拖拽选中内容。a background selection。
五、参考
官方介绍
– Documentation Archive: Drag and Drop Programming Topics
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DragandDrop/DragandDrop.html
– Introduction to Drag and Drop
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DragandDrop/DragandDrop.html
– Human Interface Guidelines :Drag and Drop
https://developer.apple.com/design/human-interface-guidelines/macos/user-interaction/drag-and-drop/
– iOS 中的 drag & drop
https://developer.apple.com/documentation/uikit/drag_and_drop
– 在 outlineView 中使用 Drag and Drop
https://developer.apple.com/documentation/appkit/cocoa_bindings/navigating_hierarchical_data_using_outline_and_split_views?language=objc
教程
– Warren Burton : Drag and Drop Tutorial for macOS
https://www.raywenderlich.com/1016-drag-and-drop-tutorial-for-macos
相关翻译:https://juejin.im/post/5b39ca1b51882574eb599a1c
– Beginning macOS Programming: Learn to Develop an Image Uploader App in Swift
https://www.appcoda.com/macos-image-uploader-app/
– ywhades:macOS 拖拽操作Drag和Drop
https://juejin.im/post/5b39ca1b51882574eb599a1c