从Finder拖放到NSTableView怪异

dwk*_*kns 2 cocoa drag-and-drop objective-c

我试图了解如何最好地将文件从Finder拖放到NSTableView,随后将列出这些文件.

我已经建立了一个小测试应用程序作为试验场.

目前,我有一个NSTableViewFileListController它的datasourse.它基本上是一个NSMutableArray File对象.

我正在尝试找出最佳/正确的方法来实现NSTableView的拖放代码.

我的第一种方法是继承NSTableView并实现所需的方法:

TableViewDropper.h

#import <Cocoa/Cocoa.h>

@interface TableViewDropper : NSTableView

@end
Run Code Online (Sandbox Code Playgroud)

TableViewDropper.m

#import "TableViewDropper.h"

@implementation TableViewDropper {
    BOOL highlight;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Initialization code here.
        NSLog(@"init in initWithCoder in TableViewDropper.h");
        [self registerForDraggedTypes:@[NSFilenamesPboardType]];
    }
    return self;

}

- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender {
    NSLog(@"performDragOperation in TableViewDropper.h");
    return YES;
}


- (BOOL)prepareForDragOperation:(id)sender {
    NSLog(@"prepareForDragOperation called in TableViewDropper.h");
    NSPasteboard *pboard = [sender draggingPasteboard];
    NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType];
    NSLog(@"%@",filenames);
    return YES;
}

- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
    highlight=YES;
    [self setNeedsDisplay: YES];
    NSLog(@"drag entered in TableViewDropper.h");

    return NSDragOperationCopy;
}

- (void)draggingExited:(id)sender
{
    highlight=NO; 
    [self setNeedsDisplay: YES];
    NSLog(@"drag exit in TableViewDropper.h");
}

-(void)drawRect:(NSRect)rect
{
    [super drawRect:rect];

    if ( highlight ) {
        //highlight by overlaying a gray border
        [[NSColor greenColor] set];
        [NSBezierPath setDefaultLineWidth: 18];
         [NSBezierPath strokeRect: rect];
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

draggingEntereddraggingExited方法都被调用,但prepareForDragOperationperformDragOperation没有.我不明白为什么不呢?

接下来我以为我将继承NSTableView的ClipView.因此,使用相同的代码上面,只是换款的头文件NSClipView类的类型我发现,prepareForDragOperationperformDragOperation现在的工作预期,但是ClipView并不突出.

如果我将NSScrollView子类化,则调用所有方法并突出显示但不是必需的.它非常薄,正如预期的那样围绕着整个NSTableView而不仅仅是我想要的表头下面的位.

所以我的问题是sublclass什么是正确的东西,我需要什么方法,以便当我从Finder执行拖放时,ClipView正确地突出显示prepareForDragOperation并被performDragOperation调用.

而且当performDragOperation成功时,该方法如何调用我的FileListController中的方法,告诉它创建一个新File对象并将其添加到NSMutableArray?

dwk*_*kns 5

回答我自己的问题.

似乎继承NSTableView(不是NSScrollView或NSClipView)是正确的方法.

在子类中包含此方法:

- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender {
return [self draggingEntered:sender];
}
Run Code Online (Sandbox Code Playgroud)

解决问题prepareForDragOperationperformDragOperation不是被调用.

要允许您在控制器类中调用方法,可以将NSTextView的delagate作为控制器.在这种情况下FileListController.

然后在performDragOperationNSTableView子类中使用类似下面的内容:

NSPasteboard *pboard = [sender draggingPasteboard];
NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType];

id delegate = [self delegate];

if ([delegate respondsToSelector:@selector(doSomething:)]) {
        [delegate performSelector:@selector(doSomething:) 
                       withObject:filenames];
}
Run Code Online (Sandbox Code Playgroud)

这将调用doSomething控制器对象中的方法.

这里更新了示例项目代码.