gpt4 book ai didi

objective-c - 我的 OS X 应用程序如何接受来自 Photos.app 的图片文件的拖放操作?

转载 作者:太空狗 更新时间:2023-10-30 03:21:55 25 4
gpt4 key购买 nike

从新的 Photos.app 拖动图片时,粘贴板中不会传递任何 URL 作为拖动信息的一部分。我的应用程序已经正确处理了从例如iPhoto、Photo Booth、Aperture、...

我尝试从 Photos.app 中拖动图片:Finder 或 Pages 可以正确处理,但 TextEdit 或 Preview 不能。 Photos.app 处理其库中存储的图片的方式似乎有所不同。

最佳答案

在深入研究 NSPasteboard 并单步执行该应用程序后,我意识到 Photos.app 正在粘贴板中传递“ promise 的文件”,并在 Apple 的邮件列表中找到了这个线程并提供了一些答案:http://prod.lists.apple.com/archives/cocoa-dev/2015/Apr/msg00448.html

这是我最终解决它的方法,在处理将文件拖放到文档中的类中。该类是处理常用拖放方法的 View Controller ,因为它位于响应链中。

一个方便的方法检测拖动的发送者是否有任何文件相关的内容:

- (BOOL)hasFileURLOrPromisedFileURLWithDraggingInfo:(id <NSDraggingInfo>)sender
{
NSArray *relevantTypes = @[@"com.apple.pasteboard.promised-file-url", @"public.file-url"];
for(NSPasteboardItem *item in [[sender draggingPasteboard] pasteboardItems])
{
if ([item availableTypeFromArray:relevantTypes] != nil)
{
return YES;
}
}
return NO;
}

如果 URL 不是“ promise 的文件”,我还有一种提取 URL 的方法:

- (NSURL *)fileURLWithDraggingInfo:(id <NSDraggingInfo>)sender
{
NSPasteboard *pasteboard = [sender draggingPasteboard];
NSDictionary *options = [NSDictionary dictionaryWithObject:@YES forKey:NSPasteboardURLReadingFileURLsOnlyKey];
NSArray *results = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:options];
return [results lastObject];
}

最后是处理掉落的方法。这不完全是我的代码,因为我简化了拖入方便方法的内部处理,这些方法允许我隐藏特定于应用程序的部分。我还有一个用于处理文件系统事件的特殊类 FileSystemEventCenter 留给读者作为练习。此外,在此处介绍的案例中,我只处理拖动一个 文件。您必须根据自己的情况调整这些部分。

- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
if ([self hasFileURLOrPromisedFileURLWithDraggingInfo:sender])
{
[self updateAppearanceWithDraggingInfo:sender];
return NSDragOperationCopy;
}
else
{
return NSDragOperationNone;
}
}

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

- (void)draggingExited:(id <NSDraggingInfo>)sender
{
[self updateAppearanceWithDraggingInfo:nil];
}

- (void)draggingEnded:(id <NSDraggingInfo>)sender
{
[self updateAppearanceWithDraggingInfo:nil];
}

- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
{
return [self hasFileURLOrPromisedFileURLWithDraggingInfo:sender];
}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
// promised URL
NSPasteboard *pasteboard = [sender draggingPasteboard];
if ([[pasteboard types] containsObject:NSFilesPromisePboardType])
{
// promised files have to be created in a specific directory
NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
if ([[NSFileManager defaultManager] createDirectoryAtPath:tempPath withIntermediateDirectories:NO attributes:nil error:NULL] == NO)
{
return NO;
}

// the files will be created later: we keep an eye on that using filesystem events
// `FileSystemEventCenter` is a wrapper around FSEvent
NSArray *filenames = [sender namesOfPromisedFilesDroppedAtDestination:[NSURL fileURLWithPath:tempPath]];
DLog(@"file names: %@", filenames);
if (filenames.count > 0)
{
self.promisedFileNames = filenames;
self.directoryForPromisedFiles = tempPath.stringByStandardizingPath;
self.targetForPromisedFiles = [self dropTargetForDraggingInfo:sender];
[[FileSystemEventCenter defaultCenter] addObserver:self selector:@selector(promisedFilesUpdated:) path:tempPath];
return YES;
}
else
{
return NO;
}
}

// URL already here
NSURL *fileURL = [self fileURLWithDraggingInfo:sender];
if (fileURL)
{
[self insertURL:fileURL target:[self dropTargetForDraggingInfo:sender]];
return YES;
}
else
{
return NO;
}
}

- (void)promisedFilesUpdated:(FDFileSystemEvent *)event
{
dispatch_async(dispatch_get_main_queue(),^
{
if (self.directoryForPromisedFiles == nil)
{
return;
}

NSString *eventPath = event.path.stringByStandardizingPath;
if ([eventPath hasSuffix:self.directoryForPromisedFiles] == NO)
{
[[FileSystemEventCenter defaultCenter] removeObserver:self path:self.directoryForPromisedFiles];
self.directoryForPromisedFiles = nil;
self.promisedFileNames = nil;
self.targetForPromisedFiles = nil;
return;
}

for (NSString *fileName in self.promisedFileNames)
{
NSURL *fileURL = [NSURL fileURLWithPath:[self.directoryForPromisedFiles stringByAppendingPathComponent:fileName]];
if ([[NSFileManager defaultManager] fileExistsAtPath:fileURL.path])
{
[self insertURL:fileURL target:[self dropTargetForDraggingInfo:sender]];
[[FileSystemEventCenter defaultCenter] removeObserver:self path:self.directoryForPromisedFiles];
self.directoryForPromisedFiles = nil;
self.promisedFileNames = nil;
self.targetForPromisedFiles = nil;
return;
}
}
});
}

关于objective-c - 我的 OS X 应用程序如何接受来自 Photos.app 的图片文件的拖放操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30110525/

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