我试图了解如何最好地将文件从Finder拖放到NSTableView,随后将列出这些文件。
我已经建立了一个小test application作为试验场。
目前我只有一个NSTableView
FileListController
作为数据。它基本上是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
draggingEntered
和draggingExited
方法都会被调用,但prepareForDragOperation
和performDragOperation
不会被调用。我不明白为什么不呢?
接下来,我想我将继承NSTableView的ClipView的子类。因此,使用与上面相同的代码,只是将头文件中的类类型转换为NSClipView,我发现prepareForDragOperation
和performDragOperation
现在按预期工作,但ClipView并不突出显示。
如果我将NSScrollView子类化,则调用所有方法并突出显示但不是必需的。它非常薄,正如预期的那样围绕着整个NSTableView而不仅仅是我喜欢的桌面下方的位。
所以我的问题是sublclass是什么是正确的,我需要什么方法,以便当我从Finder执行拖放操作时,ClipView会正确突出显示prepareForDragOperation
和performDragOperation
调用。
当performDragOperation
成功时,该方法如何调用FileListController中的方法,告诉它创建一个新的File
对象并将其添加到NSMutableArray?
答案 0 :(得分:5)
回答我自己的问题。
似乎继承NSTableView(不是NSScrollView或NSClipView)是正确的方法。
在子类中包含此方法:
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender {
return [self draggingEntered:sender];
}
解决了prepareForDragOperation
和performDragOperation
未被调用的问题。
要允许您在控制器类中调用方法,可以将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
方法。