将承诺的文件拖放到 Dock 中的应用程序图标上

Posted

技术标签:

【中文标题】将承诺的文件拖放到 Dock 中的应用程序图标上【英文标题】:Dropping promised files on to application icon in Dock 【发布时间】:2016-02-20 23:24:36 【问题描述】:

当拖放到 Dock 中的应用程序图标时,是否可以在沙盒应用程序中打开承诺的文件 NSFilesPromisePboardType? Dock 图标正在接受拖放,但从未调用过 -application:openFile:

我找到的唯一参考是预沙箱: Accepting iCal events dropped on my application's icon

rdar://47917787

【问题讨论】:

【参考方案1】:

让我们分解一下:NSApplicationNSDocumentController 在基于NSDocument 的应用程序中为您免费提供-application:openFile:-openDocumentWithContentsOfURL:display:completionHandler:,以防NSFilenamesPboardTypeNSURLPboardType 掉落。

注意:我认为在后台这是使用kCoreEventClass/kAEOpenDocumentskInternetEventClass/kAEGetURL 的 NSAppleEventManager 事件处理程序实现的。

不幸的是,他们不处理NSFilesPromisePboardType

让我们刷新我们的粘贴板知识:粘贴板在所有应用程序中共享。有用于复制、查找和拖动等任务的默认粘贴板。

当拖动开始时,应用程序会写入共享的拖动粘贴板。所以我们现在需要的只是关于拖放到 Dock 图标上的通知。

这就是NSService 发挥作用的地方:

<key>NSServices</key>
<array>
    <dict>
        <key>NSMessage</key>
        <string>openService</string>
        <key>NSSendTypes</key>
        <array>
            <string>public.data</string>
        </array>
        <key>NSMenuItem</key>
        <dict>
            <key>default</key>
            <string>Open</string>
        </dict>
    </dict>
</array>

并在代码中设置:

- (void)applicationWillFinishLaunching:(NSNotification *)notification

    [NSApp setServicesProvider:self];


- (void)openService:(NSPasteboard *)serviceBoard
           userData:(NSString *)userData
              error:(NSString **)error


需要注意的是NSService 粘贴板不是NSDragPboard 粘贴板。

但是它们都是共享的,所以我们可以访问我们想要的:

NSPasteboard *dragPboard = [NSPasteboard pasteboardWithName:NSDragPboard];

if ([[dragPboard types] containsObject:NSFilesPromisePboardType])


下一个问题是我们没有-[NSDraggingInfo namesOfPromisedFilesDroppedAtDestination:]

#import <ApplicationServices/ApplicationServices.h>

好老的 Carbon 让我们得到了保障。

    PasteboardRef pboardRef = NULL;
    PasteboardCreate((__bridge CFStringRef)NSDragPboard, &pboardRef);
    PasteboardSetPasteLocation(pboardRef, (__bridge CFURLRef)temporaryDirectory);

    NSString *urlString = [dragPboard stringForType:(NSString *)kPasteboardTypeFileURLPromise];

    CFRelease(pboardRef);

从这里开始像任何其他承诺文件一样处理。

【讨论】:

我想将一封电子邮件从 Mail 拖到我的应用程序的 Dock 图标。我使用了上面的代码(将 NSService 键添加到我的 Info.plist 文件中,设置服务提供者并添加方法 openService)。但是方法 openService 没有被调用。我能做什么?

以上是关于将承诺的文件拖放到 Dock 中的应用程序图标上的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 将邮件从 Mail 拖到 Dock 上

如何判断在 Dock 上放置期间修饰键是不是已按下

拖放到桌面图标

将 Windows 桌面快捷方式拖放到 listView

拖放到 QTreeView 中的 QStandardItemModel 不起作用

Keka 1.1.20 macOS 压缩文件管理器