使用NSDocument打开任何文件夹

时间:2012-12-20 10:15:55

标签: objective-c cocoa file-type nsdocument

我正在尝试编写一个可以打开NSDocument子类中的任何文件夹的应用程序,但无法找出正确的Info.plist设置。重要的是我的应用程序不应该使用捆绑包,也不能使用具有特定文件扩展名的文件夹,只能打开任何文件夹。

我尝试了什么:

  • 如果我将文档类型扩展名设置为空字符串,则文件打开面板不允许选择任何文件
  • 如果我将文档类型扩展名设置为*,那么文件打开面板会启用所有文件但不会启用文件夹:文件夹会像在finder中一样打开
  • 如果我将文件夹扩展名设置为文档类型扩展名,我可以将文件打开对话框中的文件夹作为文档打开(这是我想要的)但我将解决方案限制在具有该扩展名的文件夹中
  • 通过将OSType设置为“fold”,文档类型标识符或名称为“public.folder”等,因为我在论坛中读到的内容对我没有明显效果。

如何在打开文件对话框中打开任何文件夹?

3 个答案:

答案 0 :(得分:6)

为了完整起见,这里有一些关于@ iKenndac答案的更多细节:

在IB中检查First Responder的哪个方法与File / Open ...菜单项相关联。就我而言,它是openDocument:。在AppDelegate中实现此方法:

-(void)openDocument:(id)sender
{
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    [panel setCanChooseFiles:NO];
    [panel setCanChooseDirectories:YES];
    [panel setAllowsMultipleSelection:NO];

    [panel beginSheetModalForWindow:nil
                  completionHandler:^(NSInteger result) {
                      if (result == NSFileHandlingPanelOKButton) {
                          NSURL* selectedURL = [[panel URLs] objectAtIndex:0];
                          NSLog(@"selected URL: %@", selectedURL);
                          NSError* error = nil;
                          [[NSDocumentController sharedDocumentController] 
                              openDocumentWithContentsOfURL:selectedURL 
                                                   display:YES 
                                                     error:&error];
                      }
                  }];
}

您仍需要在Info.plist中定义文档类型,将标识符(LSItemContentTypes)字段设置为public.folder

答案 1 :(得分:3)

如果不编写一些自定义代码,您可能无法做到这一点。

您需要手动提供NSOpenPanel,如下所示:

NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseFiles:NO];
[panel setCanChooseDirectories:YES];

[panel beginSheetForDirectory:nil
                         file:nil
               modalForWindow:[self window]
                modalDelegate:self
               didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
                  contextInfo:nil];

以这种方式呈现的开放式面板将让用户选择他们想要的任何目录。您可以实现NSOpenPanel的委托方法来验证每个文件夹,如果需要,可以启用/禁用。

答案 2 :(得分:2)

就像今天人们如何做到的最新摘要一样,这里是我必须做的一步一步的指导:

  1. 使用Xcode从 Cocoa应用程序模板创建应用程序项目。

  2. 检查创建基于文档的应用程序,并将其中的任何内容留给"文档扩展程序" (如果您在此处删除文件扩展名,它将拒绝启用"下一步"按钮,因此我们稍后会这样做。)

  3. 点击您的项目图标,转到信息标签,然后转到文档类型

  4. 删除扩展程序字段的内容。我们的文件夹不需要特定的文件名后缀

  5. public.folder 写入标识符字段。

  6. CFBundleTypeOSTypes 数组中的其他文档类型属性下,添加一个条目 fold (只有这四个小写字母)。 不确定是否有必要,但它至少是正确的。

  7. 确保文档以捆绑方式分发

  8. 为项目创建一个包含以下方法的NSDocumentController子类。将其命名为E.g. ULIFolderDocumentController

  9.     -(void)openDocument:(id)sender
        {
            NSOpenPanel *panel = [NSOpenPanel openPanel];
            [panel setCanChooseFiles:NO];
            [panel setCanChooseDirectories:YES];
            [panel setAllowsMultipleSelection:NO];
    
            [panel beginWithCompletionHandler: ^( NSInteger result )
            {
                if (result == NSFileHandlingPanelOKButton)
                {
                    NSURL* selectedURL = [[panel URLs] objectAtIndex:0];
                    NSLog(@"selected URL: %@", selectedURL);
                    [self openDocumentWithContentsOfURL: selectedURL
                            display: YES
                            completionHandler: ^(NSDocument * _Nullable document, BOOL documentWasAlreadyOpen, NSError * _Nullable error)
                            {
                                NSLog(@"%spened document %@ (%@)", (documentWasAlreadyOpen? "Reo" : "O"), document, error);
                            }];
                }
            }];
        }
    
    1. 在您的应用代表的-init方法中添加一行,以加载您的子类而不是NSDocumentController。这很简单,只需请求共享对象:
    2.     [ULIFolderDocumentController sharedDocumentController]; // Override system's NSDocumentController with ours.
      
      1. 试试吧! :)