我如何知道从NSSavePanel中选择了哪种文件类型?

时间:2014-08-17 08:35:21

标签: macos cocoa uti nssavepanel

我正在为Mavericks系统编写应用程序。我正在调用NSSavePanel来保存文件。我可以给面板一个UA的NSArray作为可能的保存类型,并且(我猜)面板将自动生成输出类型的附件视图。在面板的完成块期间,我可以使用面板的“URL”属性来获取文件(可能创建和写入)。但似乎没有任何属性可以指示选择了哪种输出类型。

我应该查看网址的文件扩展名吗?这是因为有一个允许自由范围扩展命名的选项吗? (我没有在这里打开那个选项。)

另外:我的UTI的NSArray是随机类型,后跟固定类型。我目前只在它不等于随机类型时添加固定类型。如果我多次使用相同的UTI,面板会崩溃,还是会崩溃重复?如果它不会崩溃,那么我可以通过无条件追加来节省时间。

1 个答案:

答案 0 :(得分:0)

对于问题:我做了一个无条件的追加,似乎没有任何崩溃。所以我猜Apple的代码确实崩溃了。

我的猜测:面板创建附件视图以在多个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 Archive)的数组。在最后if中,我从目标网址的文件扩展名生成UTI列表,看看MIME和扩展阵列中是否至少有一个UTI重叠,如果有&#39则选择原始源数据;如果没有(即URL具有附加的Web存档扩展名),则重叠或创建Web存档数据,并将该数据写入磁盘。

请注意,如果原始数据本身就是Web存档,则它将与原始UTI数组匹配并直接转储其数据。我原来是用另一种方式;加载的Web存档将保存为存档存档。如果您尝试加载第二个存档(尝试第三轮),这会破坏文件大小与垃圾混乱。现在他们除了创作日期之外都是相同的。