macos - 自定义 NSView 拖动目的地

标签 macos cocoa drag-and-drop osx-lion

我正在尝试创建一个简单的 NSView,允许将 Finder 中的文件夹拖到其上。文件夹路径是我希望 View 接受为可拖动项目的唯一内容。我一直在尝试遵循 Apple documentation ,但到目前为止没有任何效果。到目前为止,我只是尝试让 View 适用于任何文件类型,但我似乎无法做到这一点。这是我到目前为止所拥有的:

-(id) initWithFrame:(NSRect)frameRect
{
    if (self = [super initWithFrame:frameRect])
    {
        NSLog(@"getting called");
        [self registerForDraggedTypes:[NSArray arrayWithObjects:NSPasteboardTypeString,
                                       NSPasteboardTypePDF,
                                       NSPasteboardTypeTIFF,
                                       NSPasteboardTypePNG,
                                       NSPasteboardTypeRTF,
                                       NSPasteboardTypeRTFD,
                                       NSPasteboardTypeHTML,
                                       NSPasteboardTypeTabularText,
                                       NSPasteboardTypeFont,
                                       NSPasteboardTypeRuler,
                                       NSPasteboardTypeColor,
                                       NSPasteboardTypeSound,
                                       NSPasteboardTypeMultipleTextSelection,
                                       NSPasteboardTypeFindPanelSearchOptions, nil]];
    }
    return self;
}

-(BOOL) prepareForDragOperation: (id<NSDraggingInfo>) sender
{
    NSLog(@"preparing for drag");

    return YES;
}

正在调用 initWithFrame: 方法,但是当我尝试拖动到 View 中时,prepareForDragOperation: 方法似乎从未被调用。我的问题:

  1. 我做错了什么?为什么 prepareForDragOperation: 没有被调用?
  2. 我需要做什么才能使拖动操作仅支持拖动文件夹?

更新

我用我能找到的每种类型更新了我的 registerForDraggedTypes: 方法。现在看起来像这样:

[self registerForDraggedTypes:[NSArray arrayWithObjects:NSPasteboardTypeString,
                               NSPasteboardTypePDF,
                               NSPasteboardTypeTIFF,
                               NSPasteboardTypePNG,
                               NSPasteboardTypeRTF,
                               NSPasteboardTypeRTFD,
                               NSPasteboardTypeHTML,
                               NSPasteboardTypeTabularText,
                               NSPasteboardTypeFont,
                               NSPasteboardTypeRuler,
                               NSPasteboardTypeColor,
                               NSPasteboardTypeSound,
                               NSPasteboardTypeMultipleTextSelection,
                               NSPasteboardTypeFindPanelSearchOptions,
                               NSStringPboardType,
                               NSFilenamesPboardType,
                               NSPostScriptPboardType,
                               NSTIFFPboardType,
                               NSRTFPboardType,
                               NSTabularTextPboardType,
                               NSFontPboardType,
                               NSRulerPboardType,
                               NSFileContentsPboardType,
                               NSColorPboardType,
                               NSRTFDPboardType,
                               NSHTMLPboardType,
                               NSURLPboardType,
                               NSPDFPboardType,
                               NSVCardPboardType,
                               NSFilesPromisePboardType,
                               NSMultipleTextSelectionPboardType, nil]];

我注意到,当我将文件夹拖到 View 中时,不会调用 prepareForDragOperation: 方法。我错过了一个步骤吗?

最佳答案

这是一个满足这些条件的简单的拖放 View :

MDDragDropView.h :

@interface MDDragDropView : NSView {
    BOOL        isHighlighted;
}

@property (assign, setter=setHighlighted:) BOOL isHighlighted;

@end

MDDragDropView.m :

@implementation MDDragDropView

@dynamic isHighlighted;

- (void)awakeFromNib {
    NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
    [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
}

- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
    NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));

    NSPasteboard *pboard = [sender draggingPasteboard];

    if ([[pboard types] containsObject:NSFilenamesPboardType]) {

        NSArray *paths = [pboard propertyListForType:NSFilenamesPboardType];
        for (NSString *path in paths) {
            NSError *error = nil;
            NSString *utiType = [[NSWorkspace sharedWorkspace]
                                       typeOfFile:path error:&error];
            if (![[NSWorkspace sharedWorkspace] 
                      type:utiType conformsToType:(id)kUTTypeFolder]) {

                [self setHighlighted:NO];
                return NSDragOperationNone;
            }
        }
    }
    [self setHighlighted:YES];
    return NSDragOperationEvery;
}

其余方法:

- (void)draggingExited:(id <NSDraggingInfo>)sender {
    [self setHighlighted:NO];
}


- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender  {
    return YES;
}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
    [self setHighlighted:NO];
    return YES;
}
- (BOOL)isHighlighted {
    return isHighlighted;
}

- (void)setHighlighted:(BOOL)value {
    isHighlighted = value;
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    if (isHighlighted) {
        [NSBezierPath setDefaultLineWidth:6.0];
        [[NSColor keyboardFocusIndicatorColor] set];
        [NSBezierPath strokeRect:self.frame];
    }
}

@end

原因prepareForDragOperation:没有被调用的原因是拖动目标序列遵循一组精确的步骤,如果前面的步骤未实现,或者已实现但返回“停止拖动操作”类型的答案,则永远不会到达后面的方法。 (在您的情况下,您似乎没有实现 draggingEntered: 方法,该方法需要返回 NSDragOperationNone 以外的其他内容才能继续序列)。

之前 prepareForDragOperation:发送时, View 首先发送一系列拖动目标消息:

单个- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender .

取决于NSDragOperation从该方法返回的掩码,如果在您的类中实现了以下内容,则将调用以下内容:

多个- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender .

取决于NSDragOperation从该方法返回掩码,然后 prepareForDragOperation:将被调用。

关于macos - 自定义 NSView 拖动目的地,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7385352/

相关文章:

macos - Mac 应用程序测试

c - 为什么我在 Ubuntu 上遇到段错误,但在 Mac 上却没有?

c++ - 在 R 中编译 C++ 代码不再有效

objective-c - 从 NSImage 对象获取最高位图表示的最佳方法是什么

swift - NSScrollView 包含 NSStackView。为什么 NSStackView 项目从底部到顶部?

xcode - 设置在共享工作区 Mac OSX 中启动的应用程序的框架位置

javascript - Dropzone.js 如何序列化值并发送?

c# - Vista & C# - 拖放问题(与海拔无关)

c++ - 如何从树列表拖放到 Windows 文件系统?

cocoa - 在 nib 中加载 IKImageBrowserViews 时,10.5 上偶尔会崩溃