macOS 开发 - Drag & Drop 拖拽的基本使用


一、概述

如果应用中有对文本、文件、图片的移动、复制操作,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

发布了164 篇原创文章 · 获赞 162 · 访问量 65万+

猜你喜欢

转载自blog.csdn.net/lovechris00/article/details/101036238