gpt4 book ai didi

objective-c - 如何使用 NSPasteboard 和 kPasteboardTypeFileURLPromise 进行复制/粘贴?

转载 作者:行者123 更新时间:2023-12-04 03:01:49 68 4
gpt4 key购买 nike

我的应用程序想为一个远程存储的文件添加一个 promise 到粘贴板,并且可能永远不会被粘贴——类似于粘贴一个从控制虚拟机或其他远程系统的 session 中复制的文件。理想情况下,用户可以粘贴到 Finder 文件夹(或桌面)中,promise 会触发,然后我们就走了。一旦触发,我愿意处理履行 promise 的问题,但我一直无法让 promise 触发。

我发现的所有 promise 代码都处理拖放,这不是我需要的功能(尽管可能需要来自 DnD 的某些东西才能使 promise 工作?)

我试过使用 NSFilePromiseProvider与代表,并将其添加到粘贴板。我可以使用剪贴板查看器查看粘贴板上的条目,但是当我在 Finder 中粘贴时,什么也没有发生,也没有调用委托(delegate)方法。我可以通过让剪贴板查看器访问条目来触发委托(delegate)方法,所以我知道很多东西都被 Hook 了。

@interface ClipboardMacPromise : NSFilePromiseProvider<NSFilePromiseProviderDelegate>
{
NSString* m_file;
}
@end
@implementation ClipboardMacPromise
- (id)initWithFileType:(NSString*)type andFile:(NSString*)file
{
m_file = file;
return [super initWithFileType:type delegate:self];
}
- (NSString *)filePromiseProvider:(NSFilePromiseProvider*)filePromiseProvider fileNameForType:(NSString *)fileType
{
return m_file;
}
- (void)filePromiseProvider:(NSFilePromiseProvider*)filePromiseProvider writePromiseToURL:(NSURL *)url completionHandler:(void (^)(NSError * _Nullable errorOrNil))completionHandler
{
// Finder can't paste, so we never get here...
}
@end

NSPasteboard* pboard = [NSPasteboard generalPasteboard];
[pboard clearContents];
NSMutableArray* items = [[NSMutableArray alloc] init];
ClipboardMacPromise* promise = [[ClipboardMacPromise alloc] initWithFileType:(NSString*)kUTTypeFileURL andFile:@"dummy.txt"];
[items addObject:promise];
[pboard writeObjects:items];

我也试过 NSPasteboardItemNSPasteboardItemDataProvider我在 kUTITypeFileURL 上设置了内容 promise .它在粘贴板上提供了非常相似的条目,但是当我粘贴到 finder 中时仍然没有 Action 。访问各个粘贴板条目时,剪贴板查看器将再次触发提供程序。 ( NSPasteboarddeclareTypes:owner: 具有相同的行为)
@interface ClipboardMacPromise : NSPasteboardItem<NSPasteboardItemDataProvider>
{
NSString* m_file;
}
@end
@implementation ClipboardMacPromise
- (id)initWithFile:(NSString*)file
{
m_file = file;
id _self = [super init];
if (_self) {
[_self setDataProvider:_self forTypes:@[(NSString*)kPasteboardTypeFileURLPromise]];
[_self setString:(NSString*)kUTTypeFileURL forType:(NSString*)kPasteboardTypeFilePromiseContent];
}
return _self;
}
- (void)pasteboard:(NSPasteboard *)pasteboard item:(NSPasteboardItem *)item provideDataForType:(NSPasteboardType)type
{
// we don't get here when we paste in Finder because
// Finder doesn't think there's anything to paste
// but using a clipboard viewer, we can force the promise to
// resolve and we do get here
}
@end

NSPasteboard* pboard = [NSPasteboard generalPasteboard];
[pboard clearContents];
NSMutableArray* items = [[NSMutableArray alloc] init];
ClipboardMacPromise* promise = [[ClipboardMacPromise alloc] initWithFile:@"file:///tmp/dummy.txt"];
[items addObject:promise];
[pboard writeObjects:items];

为了完整起见,这是我的 Carbon 尝试,因为 Pasteboard.h 似乎详细说明了它在复制/粘贴场景中应该如何工作......但它仍然没有为 Finder 提供它正在寻找的东西。生成的剪贴板条目在三个实现之间看起来非常相似。
OSStatus PasteboardPromiseKeeperProc(PasteboardRef pasteboard, PasteboardItemID item, CFStringRef flavorType, void * _Nullable context)
{
// 6) The sender's promise callback for kPasteboardTypeFileURLPromise is called.
string s = "dummy.txt";
CFDataRef inData = CFDataCreate(kCFAllocatorDefault, (UInt8*)s.c_str(), s.size());
PasteboardPutItemFlavor(pasteboard, item, flavorType, inData, 0);
return noErr;
}

PasteboardRef p = NULL;
PasteboardCreate(kPasteboardClipboard, &p);
PasteboardClear(p);
PasteboardSetPromiseKeeper(p, &PasteboardPromiseKeeperProc, this);

// 1) The sender promises kPasteboardTypeFileURLPromise for a file yet to be created.
PasteboardPutItemFlavor(p, (PasteboardItemID)1, kPasteboardTypeFileURLPromise, kPasteboardPromisedData, 0);
// 2) The sender adds kPasteboardTypeFilePromiseContent containing the UTI describing the file's content.
PasteboardPutItemFlavor(p, (PasteboardItemID)2, kPasteboardTypeFilePromiseContent,CFStringCreateExternalRepresentation(NULL, kUTTypeFileURL, kCFStringEncodingUTF8, 0), 0);

Finder 确实在粘贴板上寻找某个 UTI,但我没有。如果我放一个 kUTTypeFileURL直接在剪贴板上,finder 似乎在提供粘贴之前实际上会检查文件是否存在(即触发 Catalina 的桌面访问提示)。

有谁知道是否或如何通过复制/粘贴而不是拖放向 Finder 提供文件 promise ?

最佳答案

看来这里的关键部分是 Finder 要求文件实际存在于磁盘上,才能为文件 URL 启用粘贴操作。这一细节排除了 promise 用于复制/粘贴的可能性——至少在 Finder 中是这样。

因此,正确的解决方案需要一个虚拟化文件系统(如 FUSE),以便可以在文件系统级别做出和履行 promise 。因此,可以将临时零长度文件的集合写入磁盘,并将实际文件 URL 添加到粘贴板。这满足了 Finder 启用粘贴的要求。然后,当进行粘贴操作时,会从虚拟化文件系统中读取文件数据,而虚拟化文件系统又可以从远程系统中检索实际数据。 Finder 并不明智。副本甚至会有一个内置的进度条!

微软的 Mac RDP 客户端似乎大多以这种方式工作,尽管我只能让它复制零长度文件,所以这可能比听起来更难。

关于objective-c - 如何使用 NSPasteboard 和 kPasteboardTypeFileURLPromise 进行复制/粘贴?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58886232/

68 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com