我正在 Mavericks 系统上编写一个应用程序。 我正在调用 NSSavePanel 来保存文件。 我可以为面板提供一个 UTI 的 NSArray 以尽可能使用保存类型,并且(我猜)面板将自动生成输出类型附件视图。 在面板的完成块期间,我可以使用面板的“URL”属性来获取要(可能创建和)写入的文件。 但似乎没有属性来指示选择了哪种输出类型。
我应该查看 URL 的文件扩展名吗? 这是因为有一个选项允许自由范围扩展命名吗? (我这里没有打开该选项。)
另外:我的 UTI NSArray 是随机类型,后跟固定类型。 目前,仅当固定类型不等于随机类型时,我才添加固定类型。 如果我多次出现相同的 UTI,面板会崩溃吗?还是会崩溃掉重复项? 如果它不会崩溃,那么我可以通过无条件追加来节省时间。
对于also问题:我进行了无条件附加,似乎没有崩溃。 所以我猜苹果的代码确实会折叠重复项。
据我猜测:该面板不会创建一个辅助视图来在多个UTI中进行选择。 (面向 NSDocument 的应用程序上的等效操作也是如此。)面板根据 UTI 数组为新文件选择一个初始(不太)秘密的扩展名。 如果您添加扩展名,并且它位于 UTI 列表中或自由范围扩展名命名已打开,面板将允许它。 否则,您会收到错误扩展警告警报。 我提到了随机类型和固定类型; 99% 的情况下,用户想要随机类型,首先会选择它,而且我不介意固定类型需要高级用户来触发它(通过添加其扩展名)。
看起来我必须使用 URL 的文件扩展名来输入我的文件。 我只有两种类型可用,随机类型是原始数据,固定类型是我始终可以生成的类型。 固定类型有一个简单的扩展,因此我可以区分我需要获取哪个数据块。 我不打开自由范围扩展命名,因为我无法使用额外的类型做任何事情。
/*!
@brief Action to save a copy of the currently displayed resource.
@param sender The object that sent this message.
*/
- (IBAction)saveDocumentTo:(id)sender
{
NSSavePanel * const panel = [NSSavePanel savePanel];
WebDataSource * const source = self.webView.mainFrame.dataSource;
NSURLResponse * const response = source.response;
NSArray * const fileTypes = (__bridge_transfer NSArray *)UTTypeCreateAllIdentifiersForTag(kUTTagClassMIMEType, (__bridge CFStringRef)response.MIMEType, NULL);
panel.allowedFileTypes = [fileTypes arrayByAddingObject:(__bridge NSString *)kUTTypeWebArchive];
panel.nameFieldStringValue = response.suggestedFilename;
panel.canSelectHiddenExtension = YES;
[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
NSError *error = nil;
if (![([fileTypes firstObjectCommonWithArray:(__bridge_transfer NSArray *)UTTypeCreateAllIdentifiersForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)panel.URL.pathExtension, NULL)] ? source.data : source.webArchive.data) writeToURL:panel.URL options:NSDataWritingAtomic error:&error]) {
[self performSelector:@selector(showError:) withObject:error afterDelay:0.0];
}
}
}];
}
你应该主要关注我正在做的事情。
fileTypes
对象获取与资源的 MIME 类型匹配的 UTI 数组。 我为面板提供了附加了固定类型(Web 存档)的数组。 在最后一个if
中,我从目标 URL 的文件扩展名生成 UTI 列表,查看 MIME 和扩展名数组中是否至少有一个 UTI 重叠,如果存在重叠,则选择原始源数据,或者如果存在则创建 Web 存档数据它没有(即 URL 具有附加的 Web Archive 扩展名),并将该数据写入磁盘。
请注意,如果原始数据本身就是 Web Archive,它将与原始 UTI 数组匹配并直接转储其数据。 我最初的想法是另一种方式;加载的网络存档将被保存为存档的存档。 如果您尝试加载第二个存档(尝试第三轮),这会导致文件大小因垃圾而膨胀,从而导致加载混乱。 现在除了创建日期之外它们是相同的。