将 FileURL 的名称写入粘贴板
Writing FileURL's name to Pasteboard
我想使用 [pasteboard writeObjects:pasteboardArray];
将一些文件URL 写入通用粘贴板,其中 pasteboard
是通用粘贴板的对象,pasteboardArray
是 NS 的 NSArray URL的。它像
这样在粘贴板上写 url
文件://localhost/Usr/
文件://localhost/Vol/
...等等
我想把这些URL写成如下
用户名
成交量
..等等
即只有 file/Directory 的名称,因为系统在复制任何 file/Directory 时所做的。
对于粘贴板上的每个项目,可以有多种类型的数据。当您将 NSURL
写入粘贴板时,它会放入诸如 public.file-url
(URL 作为 UTF-8 文本)、NSFilenamesPboardType
(文件路径字符串数组,序列化为 XML 属性 列表),"Apple URL pasteboard type"(文件 URL 字符串数组,序列化为 XML 属性 列表),以及public.utf8-plain-text
(URL 为 UTF-8 文本)。
当您在 Finder 中复制文件时,它会放置许多相同类型的文件,尽管它似乎首先将 URL 转换为文件引用 URL。此外,它将文件的图标作为 ICNS 和 TIFF 图像。但是,public.utf8-plain-text
类型只有文件名,而不是 URL。该字符串也以 public.utf16-plain-text
.
类型存在
因此,据推测,Finder 并不是简单地使用 -writeObjects:
来填充粘贴板。它可能使用 -declareTypes:owner:
and/or -addTypes:owner:
后跟 -set...:forType:
(例如 -setString:forType:
)的旧方法。或者它可能正在使用其 -set...:forType:
方法构建具有所需类型和数据的 NSPasteboardItem
实例,然后将这些项目写入粘贴板。
根据您的需要,这样做可能就足够了:
[pasteboard writeObjects:arrayOfURLs];
NSMutableString* names = [NSMutableString string];
for (NSURL* url in arrayOfURLs)
{
NSString* name;
if ([url getResourceValue:&name forKey:NSURLLocalizedNameKey error:NULL])
{
if (names.length)
[names appendString:@"\r"];
[names appendString:name];
}
}
if (names.length)
{
[pasteboard addTypes:@[(__bridge NSString*)kUTTypeUTF8PlainText] owner:nil];
[pasteboard setString:names forType:(__bridge NSString*)kUTTypeUTF8PlainText];
}
注意:当你向粘贴板写入多个URL时,有多个项目,每个项目有多种类型。但是,某些类型是针对整个集合的,而那些仅适用于第一项。普通字符串类型和 NSFilenamesPboardType
是这样的。上面的代码将纯字符串放在第一个项目上,并包括所有 URL 的显示名称,用回车符 return 分隔(这就是 Finder 所做的)。
以上所述,不清楚您是否希望粘贴板包含 只是 URL 的显示名称而不是 URL 自己在任何表示中。在这种情况下,只需从 URL 的显示名称创建一个字符串数组并将该数组传递给 -writeObjects:
即可。
更新:
我找到了一种方法,可以更接近 Finder 的功能,同时走捷径:
NSMutableArray* arrayOfPaths = [arrayOfURLs valueForKey:@"path"];
[pasteboard setPropertyList:arrayOfPaths forType:NSFilenamesPboardType];
NSMutableString* names = [NSMutableString string];
BOOL first = YES;
for (NSURL* url in arrayOfURLs)
{
NSString* name;
if (![url getResourceValue:&name forKey:NSURLLocalizedNameKey error:NULL])
name = @"";
if (first)
first = NO;
else
[names appendString:@"\r"];
[names appendString:name];
}
if (names.length)
{
[pasteboard addTypes:@[(__bridge NSString*)kUTTypeUTF8PlainText] owner:nil];
[pasteboard setString:names forType:(__bridge NSString*)kUTTypeUTF8PlainText];
}
当您为类型 NSFilenamesPboardType
设置数据时,Cocoa 会自动设置多个项目,每个项目对应数组中的一个元素。第二个和后续的每个都只有一个类型 public.file-url
。第一项具有该类型以及 Finder 放置在粘贴板上的大多数其他类型,而不是图像类型。然后,只需在第一项上设置字符串值即可。
包含 NSFilenamesPboardType
类型很重要,因为在添加对多个粘贴板项目的支持之前,这是多个文件在粘贴板上的表示方式。一些应用程序可能仍然依赖于它。
此外,如果您分别为每个项目提供字符串数据(如您自己的回答中所做的那样),那么应用程序会从整个粘贴板中请求字符串(即 [pasteboard stringForType:NSStringPboardType]
)获取它们与换行符连接。这与从 Finder 复制文件时应用程序获得的内容略有不同,其中字符串与回车符 return 连接。某些应用可能无法很好地应对这种差异。
NSMutableArray *archive=[NSMutableArray array];
for (int i = 0; i < [pasteboardArray count]; i++) {
NSPasteboardItem *item = [[NSPasteboardItem alloc] init];
NSURL *url = [pasteboardArray objectAtIndex:i];
if (url != nil) {
[item setString:[url lastPathComponent] forType:(__bridge NSString*)kUTTypeUTF8PlainText];
NSString *str = [NSString stringWithFormat:@"%@",url];
[item setData:[str dataUsingEncoding:NSUTF8StringEncoding] forType:(__bridge NSString*)kUTTypeFileURL];
}
[archive addObject:item];
}
[pasteboard writeObjects:archive];
这对我有用,其中 pasteboard
是通用粘贴板的对象,pasteboardArray
是 NSURL 的 NSArray。欢迎任何更好的解决方案...
我想使用 [pasteboard writeObjects:pasteboardArray];
将一些文件URL 写入通用粘贴板,其中 pasteboard
是通用粘贴板的对象,pasteboardArray
是 NS 的 NSArray URL的。它像
文件://localhost/Usr/
文件://localhost/Vol/
...等等
我想把这些URL写成如下
用户名
成交量
..等等
即只有 file/Directory 的名称,因为系统在复制任何 file/Directory 时所做的。
对于粘贴板上的每个项目,可以有多种类型的数据。当您将 NSURL
写入粘贴板时,它会放入诸如 public.file-url
(URL 作为 UTF-8 文本)、NSFilenamesPboardType
(文件路径字符串数组,序列化为 XML 属性 列表),"Apple URL pasteboard type"(文件 URL 字符串数组,序列化为 XML 属性 列表),以及public.utf8-plain-text
(URL 为 UTF-8 文本)。
当您在 Finder 中复制文件时,它会放置许多相同类型的文件,尽管它似乎首先将 URL 转换为文件引用 URL。此外,它将文件的图标作为 ICNS 和 TIFF 图像。但是,public.utf8-plain-text
类型只有文件名,而不是 URL。该字符串也以 public.utf16-plain-text
.
因此,据推测,Finder 并不是简单地使用 -writeObjects:
来填充粘贴板。它可能使用 -declareTypes:owner:
and/or -addTypes:owner:
后跟 -set...:forType:
(例如 -setString:forType:
)的旧方法。或者它可能正在使用其 -set...:forType:
方法构建具有所需类型和数据的 NSPasteboardItem
实例,然后将这些项目写入粘贴板。
根据您的需要,这样做可能就足够了:
[pasteboard writeObjects:arrayOfURLs];
NSMutableString* names = [NSMutableString string];
for (NSURL* url in arrayOfURLs)
{
NSString* name;
if ([url getResourceValue:&name forKey:NSURLLocalizedNameKey error:NULL])
{
if (names.length)
[names appendString:@"\r"];
[names appendString:name];
}
}
if (names.length)
{
[pasteboard addTypes:@[(__bridge NSString*)kUTTypeUTF8PlainText] owner:nil];
[pasteboard setString:names forType:(__bridge NSString*)kUTTypeUTF8PlainText];
}
注意:当你向粘贴板写入多个URL时,有多个项目,每个项目有多种类型。但是,某些类型是针对整个集合的,而那些仅适用于第一项。普通字符串类型和 NSFilenamesPboardType
是这样的。上面的代码将纯字符串放在第一个项目上,并包括所有 URL 的显示名称,用回车符 return 分隔(这就是 Finder 所做的)。
以上所述,不清楚您是否希望粘贴板包含 只是 URL 的显示名称而不是 URL 自己在任何表示中。在这种情况下,只需从 URL 的显示名称创建一个字符串数组并将该数组传递给 -writeObjects:
即可。
更新:
我找到了一种方法,可以更接近 Finder 的功能,同时走捷径:
NSMutableArray* arrayOfPaths = [arrayOfURLs valueForKey:@"path"];
[pasteboard setPropertyList:arrayOfPaths forType:NSFilenamesPboardType];
NSMutableString* names = [NSMutableString string];
BOOL first = YES;
for (NSURL* url in arrayOfURLs)
{
NSString* name;
if (![url getResourceValue:&name forKey:NSURLLocalizedNameKey error:NULL])
name = @"";
if (first)
first = NO;
else
[names appendString:@"\r"];
[names appendString:name];
}
if (names.length)
{
[pasteboard addTypes:@[(__bridge NSString*)kUTTypeUTF8PlainText] owner:nil];
[pasteboard setString:names forType:(__bridge NSString*)kUTTypeUTF8PlainText];
}
当您为类型 NSFilenamesPboardType
设置数据时,Cocoa 会自动设置多个项目,每个项目对应数组中的一个元素。第二个和后续的每个都只有一个类型 public.file-url
。第一项具有该类型以及 Finder 放置在粘贴板上的大多数其他类型,而不是图像类型。然后,只需在第一项上设置字符串值即可。
包含 NSFilenamesPboardType
类型很重要,因为在添加对多个粘贴板项目的支持之前,这是多个文件在粘贴板上的表示方式。一些应用程序可能仍然依赖于它。
此外,如果您分别为每个项目提供字符串数据(如您自己的回答中所做的那样),那么应用程序会从整个粘贴板中请求字符串(即 [pasteboard stringForType:NSStringPboardType]
)获取它们与换行符连接。这与从 Finder 复制文件时应用程序获得的内容略有不同,其中字符串与回车符 return 连接。某些应用可能无法很好地应对这种差异。
NSMutableArray *archive=[NSMutableArray array];
for (int i = 0; i < [pasteboardArray count]; i++) {
NSPasteboardItem *item = [[NSPasteboardItem alloc] init];
NSURL *url = [pasteboardArray objectAtIndex:i];
if (url != nil) {
[item setString:[url lastPathComponent] forType:(__bridge NSString*)kUTTypeUTF8PlainText];
NSString *str = [NSString stringWithFormat:@"%@",url];
[item setData:[str dataUsingEncoding:NSUTF8StringEncoding] forType:(__bridge NSString*)kUTTypeFileURL];
}
[archive addObject:item];
}
[pasteboard writeObjects:archive];
这对我有用,其中 pasteboard
是通用粘贴板的对象,pasteboardArray
是 NSURL 的 NSArray。欢迎任何更好的解决方案...