【问题标题】:Drag and Drop from the Finder to a NSTableView weirdness从 Finder 拖放到 NSTableView 怪异
【发布时间】:2014-04-11 09:22:33
【问题描述】:

我正在尝试了解如何最好地将文件从 Finder 拖放到 NSTableView,该 NSTableView 随后将列出这些文件。

我建了一个小test application 作为试验场。

目前我有一个 NSTableViewFileListController 作为数据源。它基本上是 File 对象的 NSMutableArray。

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

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

TableViewDropper.h

#import <Cocoa/Cocoa.h>

@interface TableViewDropper : NSTableView

@end

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

draggingEntereddraggingExited 方法都会被调用,但 prepareForDragOperationperformDragOperation 不会。我不明白为什么不呢?

接下来我想我会将 NSTableView 的 ClipView 子类化。因此,使用与上面相同的代码并将头文件中的类类型更改为 NSClipView,我发现 prepareForDragOperationperformDragOperation 现在可以按预期工作,但是 ClipView 没有突出显示。

如果我将 NSScrollView 子类化,那么所有方法都会被调用并且突出显示有效,但不是必需的。它非常薄,正如预期的那样围绕整个 NSTableView 而不仅仅是我想要的表格标题下方的位。

所以我的问题是 sublclass 的正确做法是什么以及我需要什么方法以便当我从 Finder 执行拖放操作时,ClipView 会正确突出显示并调用 prepareForDragOperationperformDragOperation

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

【问题讨论】:

标签: objective-c cocoa drag-and-drop


【解决方案1】:

回答我自己的问题。

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

在子类中包含这个方法:

- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender {
return [self draggingEntered:sender];
}

解决prepareForDragOperationperformDragOperation不被调用的问题。

为了允许您在控制器类中调用方法,您将 NSTextView 的 delagate 设置为控制器。在这种情况下FileListController

然后在 NSTableView 子类中的performDragOperation 中使用类似:

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

id delegate = [self delegate];

if ([delegate respondsToSelector:@selector(doSomething:)]) {
        [delegate performSelector:@selector(doSomething:) 
                       withObject:filenames];
}

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

Updated example project code here.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-05
    • 2011-10-04
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 2010-10-13
    • 1970-01-01
    相关资源
    最近更新 更多