在macOS系统中,我们可以使用NSOpenPanel
和NSSavePanel
来实现文件的读取和写入。但是iOS并没有对应的类,这是因为虽然都是支持沙盒系统。macOS的沙盒和iOS的沙盒还是存在差异的。
macOS和iOS在沙盒部分的差异
macOS的沙盒是可选项,应用可以选择使用沙盒,也可以选择不使用。不过如果你想在苹果商店上架,就必须使用。不使用沙盒的应用,只能使用其它的渠道进行分发。但是仍旧可以使用Xcode进行打包,然后通过苹果的验证即可。
iOS的沙盒是必选项。应用必须使用沙盒。
macOS的应用使用NSOpenpanel
打开用户选中的文件时,会自动获得选中文件的读取/写入权限。这被苹果称为所在位置读取。LSSupportsOpeningDocumentsInPlace
iOS的应用读取外部的文件的时候,不能自动获取相应的权限。因此,需要使用URL
的startAccessingSecurityScopedResource()
和stopAccessingSecurityScopedResource()
函数来获取临时的权限。
由于iOS的沙盒隔离的更加彻底。要选择读取文件,有两种方式,一种是类似打开窗口的UIDocumentPickerViewController
,一种是用于文档类型应用的UIDocumentBrowserViewController
。二者最大的区别,是后者支持创建空白文件。
SwiftUI
到了SwiftUI的时代,苹果同样提供了我们两种方式,分别对应iOS的UIDocumentPickerViewController
和UIDocumentBrowserViewController
。
函数fileImporter(isPresented:allowedContentTypes:onCompletion:)
这个函数对应的是UIDocumentPickerViewController
。它的缺点是相比它对应的类,它缺少该类的一些特性。比如,不能在打开时预设文件夹。
DocumentGroup
这个结构体,对应类UIDocumentBrowserViewController
。一旦你使用了它,你的应用就自动获得了UIDocumentBrowserViewController
的功能。
如何选择
上面的分类谈完之后,下面谈谈使用时要如何选择。
首先,如果你的应用符合文件类型应用的特征,那么可以优先选择DocumentGroup
。因为它可以是你的应用获得更多的预制特性,这样应用编写起来会更加简单。
不过,DocumentGroup
的使用过程,我也遇到了一些无法克服的困难。如果你的应用有如下的需求,那么就别使用DocumentGroup
了。
- 打开的文件类型是package类型的子类,或者是package类型子类内部的一部分。
- 不需要创建空文件的功能。
有些文件本身是文件夹,但是在Finder中显示为单独的文件。这类文件都属于package类型的子类。
我遇到的问题是,DocumentGroup
无法打开这个类型文件,虽然类型注册是成功的。
有时我们的应用虽然符合文件类型应用的范围,但是我们本身并不创建空文件,而是使用其它应用创建的文件。
比如翻译xliff文件的应用。本身不需要创建看的xliff文件。而是使用其它应用,如Xcode,导出的xliff文件。
其它的一些使用技巧
需要注意的是,在使用URL
的startAccessingSecurityScopedResource()
和stopAccessingSecurityScopedResource()
函数的时候,这个URL应该是沙盒传递过来的那个最原始的URL。如果你经过计算,使用了它内部的其它URL,那么在写入操作的时候,也必须调用原始的URL,而不能用计算的URL。如果你使用了后者,则操作不会成功。