使用 NSDocument 打开任何文件夹
Posted
技术标签:
【中文标题】使用 NSDocument 打开任何文件夹【英文标题】:Open any folder with NSDocument 【发布时间】:2012-12-20 10:15:54 【问题描述】:我正在尝试编写一个可以打开 NSDocument 子类中的任何文件夹但无法确定正确的 Info.plist 设置的应用程序。重要的是,我的应用程序不应使用捆绑包,也不应使用具有特定文件扩展名的文件夹,而只能打开任何文件夹。
我尝试了什么:
如果我将文档类型扩展名设置为空字符串,则文件打开面板不允许选择任何文件 如果我将文档类型扩展名设置为 *,则文件打开面板会启用所有文件,但不会启用文件夹:文件夹会像在 finder 中一样打开 如果我将文件夹扩展名设置为文档类型扩展名,我可以在文件打开对话框中将文件夹作为文档打开(这是我想要的),但我的解决方案仅限于具有该扩展名的文件夹 通过将 OSType 设置为“fold”,将文档类型标识符或名称设置为“public.folder”等,正如我在论坛中看到的那样,对我没有明显的影响。如何在打开文件对话框中打开任何文件夹?
【问题讨论】:
【参考方案1】:为了完整起见,这里是@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 中定义一个 Document Type,将 Identifier (LSItemContentTypes) 字段设置为 public.folder
。
【讨论】:
是的,但我认为你应该在NSDocumentController
子类中这样做。【参考方案2】:
如果不编写一些自定义代码,您可能无法做到这一点。
您需要手动提交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
的委托方法来验证每个文件夹并在需要时启用/禁用。
【讨论】:
【参考方案3】:正如对今天如何做到这一点的更新摘要一样,这里是我必须做的分步指南:
使用 Xcode 从 Cocoa 应用程序 模板创建应用程序项目。
选中创建基于文档的应用程序,并为“文档扩展名”留下任何建议(如果您正确删除文件扩展名,它将拒绝启用“下一步”按钮在这里,所以我们稍后会这样做)。
点击您的项目图标,转到信息选项卡和文档类型。
删除 Extensions 字段的内容。我们的文件夹不需要特定的文件名后缀
将 public.folder 写入 Identifier 字段。
在 CFBundleTypeOSTypes 数组的 Additional document type properties 下添加一个条目,fold(仅这四个小写字母)。 不确定是否有必要,但至少是正确的。
确保文档以捆绑包形式分发未检查。
为您的项目创建一个包含以下方法的NSDocumentController
子类。命名它例如ULIFolderDocumentController
.
-
在您的应用程序委托的
-init
方法中添加一行来加载您的子类,而不是NSDocumentController
。这很简单,只需请求共享对象:
-
试试吧! :)
【讨论】:
2022 年更新: 这基本上仍然有效,但有一些细微差别: - 您需要在 Document Types 部分中进行一些更改现在在 Imported Type Identifiers 部分。看起来标识符在两个部分之间也是重复的。 - 我没有设法添加其他文档类型属性,但它似乎仍然有效。 - 我没有在任何地方发现 Document 以捆绑包形式分发,但它似乎仍然有效。所以大多数情况下,只要尽可能按照说明进行操作,它们仍然可以工作! 更多注意事项: - 在NSDocument
子类中,将 read(from data: Data, ofType typeName: String)
方法替换为 read(from url: URL, ofType typeName: String)
方法,因为您将从磁盘上的文件夹中读取,而不是使用 macOS为您读取数据 - 在 NSDocumentController.h
中,Apple 建议从 applicationWillFinishLaunching:
实例化您的自定义文档控制器,而不是从 init:
实例化 - 不确定有什么区别以上是关于使用 NSDocument 打开任何文件夹的主要内容,如果未能解决你的问题,请参考以下文章
如何在 NSDocument 加载之前拦截 openDocument 的结果?