Cocoa 如何覆盖NSTextField中的拖动接收?

Cocoa 如何覆盖NSTextField中的拖动接收?,cocoa,drag-and-drop,nstextfield,Cocoa,Drag And Drop,Nstextfield,我是用斯威夫特写的。我有一个NSTextField,我在IB中分配了一个类,定义如下: class MyTextField : NSTextField, NSDraggingDestination { 我已经在子类中重写了draggingEntered、draggingupdate、preparefordraguoperation、performdraguoperation,但是这些都没有被调用,系统只是在它认为合适的时候将内容放入字段中。我想处理拖动,因为除其他外,如果用户将文件拖动到字段中

我是用斯威夫特写的。我有一个NSTextField,我在IB中分配了一个类,定义如下:

class MyTextField : NSTextField, NSDraggingDestination {
我已经在子类中重写了draggingEntered、draggingupdate、preparefordraguoperation、performdraguoperation,但是这些都没有被调用,系统只是在它认为合适的时候将内容放入字段中。我想处理拖动,因为除其他外,如果用户将文件拖动到字段中,我不希望出现将URL粘贴到字段中的默认行为。相反,如果他这样做了,我想得到文件的显示名并使用它


我缺少什么?

实现协议的任何对象的责任之一是维护一个数据类型数组,该数组通知其他人什么样的数据将触发您在问题中提到的方法。为了允许您的子类处理Finder或desktop中的拖拽,我发现您需要注册三种粘贴板类型

/* Sorry, not using Swift yet */

// MyNSTextField.m

- (void)awakeFromNib {
    [self registerForDraggedTypes:@[NSPasteboardTypeString,
                                    NSURLPboardType,
                                    NSFilenamesPboardType]];
}
至少在OSX10.9上,这足以激发您的Draggingered方法。如果粘贴板上只需要文件名,而不是完整的URL或路径,则需要i提取名称,ii清除粘贴板,iii将名称重新添加到粘贴板上:

- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {

    NSDragOperation operation = NSDragOperationNone;

    NSPasteboard *pBoard = [sender draggingPasteboard];
    NSArray *array = [pBoard readObjectsForClasses:@[[NSURL class], [NSString class]]
                                           options:nil];

    if ([array count] > 0) {
        NSString *filename;
        if ([[array firstObject] isKindOfClass:[NSURL class]]) {
            // Possibly a file dragged from Finder
            NSURL *url = [array firstObject];
            filename = [[url pathComponents] lastObject];

        } else if ([[array firstObject] isKindOfClass:[NSString class]]) {
            // Possibly a file dragged from the desktop
            NSString *path = [array firstObject];
            BOOL isPath = [[NSFileManager defaultManager] fileExistsAtPath:path];
            if (isPath) {
                filename = [path lastPathComponent];
            }
        }

        if (filename) {
            [pBoard clearContents];
            [pBoard setData:[filename dataUsingEncoding:NSUTF8StringEncoding]
                    forType:NSPasteboardTypeString];
            operation = NSDragOperationGeneric;
        }
    }

    return operation;
}

在此方法中,您可以将文本字段的内容与粘贴板的内容进行比较,如果您的字段现在包含有效的系统路径,并且此路径与粘贴板的内容匹配,则您知道需要调整文本字段中的字符串。幸运的是,这似乎发生得很快,看起来就像正常的粘贴操作。

谢谢,但这不是问题所在。问题是,默认情况下,如果用户将文件拖动到NSTextField中,文件的URL将粘贴到该字段中。即使我只为public.plain text注册字段或基础NSTextView,也会发生这种情况。你说得对。除了指定NSPasteboardTypeString之外,您还需要指定NSURLBoardType,以及NSFileNamespoardType(为了更好的测量),请参阅更新的答案。尝试了几种方法后,我通过将NSTextView子类化并在windowWillReturnFieldEditor中返回我的子类解决了这个问题。我的子类重写performDragOperation,并在其实现中在发件人的粘贴板上查找public.file-url字符串。如果找到一个,它将获取项目的显示名称并将其粘贴到字段中,替换任何选定的文本。这并不理想,因为它不会将其插入用户释放鼠标的位置,但它比默认行为要好得多。
// From NSTextFieldDelegate Protocol
- (void)textDidChange:(NSNotification *)notification