肇鑫的技术博客

业精于勤,荒于嬉

SwiftUI读取、保存,界面的选择

在macOS系统中,我们可以使用NSOpenPanelNSSavePanel来实现文件的读取和写入。但是iOS并没有对应的类,这是因为虽然都是支持沙盒系统。macOS的沙盒和iOS的沙盒还是存在差异的。

macOS和iOS在沙盒部分的差异

macOS的沙盒是可选项,应用可以选择使用沙盒,也可以选择不使用。不过如果你想在苹果商店上架,就必须使用。不使用沙盒的应用,只能使用其它的渠道进行分发。但是仍旧可以使用Xcode进行打包,然后通过苹果的验证即可。

iOS的沙盒是必选项。应用必须使用沙盒。

macOS的应用使用NSOpenpanel打开用户选中的文件时,会自动获得选中文件的读取/写入权限。这被苹果称为所在位置读取。LSSupportsOpeningDocumentsInPlace

iOS的应用读取外部的文件的时候,不能自动获取相应的权限。因此,需要使用URLstartAccessingSecurityScopedResource()stopAccessingSecurityScopedResource()函数来获取临时的权限。

由于iOS的沙盒隔离的更加彻底。要选择读取文件,有两种方式,一种是类似打开窗口的UIDocumentPickerViewController,一种是用于文档类型应用的UIDocumentBrowserViewController。二者最大的区别,是后者支持创建空白文件。

SwiftUI

到了SwiftUI的时代,苹果同样提供了我们两种方式,分别对应iOS的UIDocumentPickerViewControllerUIDocumentBrowserViewController

函数fileImporter(isPresented:allowedContentTypes:onCompletion:)

这个函数对应的是UIDocumentPickerViewController。它的缺点是相比它对应的类,它缺少该类的一些特性。比如,不能在打开时预设文件夹。

DocumentGroup

这个结构体,对应类UIDocumentBrowserViewController。一旦你使用了它,你的应用就自动获得了UIDocumentBrowserViewController的功能。

如何选择

上面的分类谈完之后,下面谈谈使用时要如何选择。

首先,如果你的应用符合文件类型应用的特征,那么可以优先选择DocumentGroup。因为它可以是你的应用获得更多的预制特性,这样应用编写起来会更加简单。

不过,DocumentGroup的使用过程,我也遇到了一些无法克服的困难。如果你的应用有如下的需求,那么就别使用DocumentGroup了。

  1. 打开的文件类型是package类型的子类,或者是package类型子类内部的一部分。
  2. 不需要创建空文件的功能。

有些文件本身是文件夹,但是在Finder中显示为单独的文件。这类文件都属于package类型的子类。
我遇到的问题是,DocumentGroup无法打开这个类型文件,虽然类型注册是成功的。
有时我们的应用虽然符合文件类型应用的范围,但是我们本身并不创建空文件,而是使用其它应用创建的文件。
比如翻译xliff文件的应用。本身不需要创建看的xliff文件。而是使用其它应用,如Xcode,导出的xliff文件。

其它的一些使用技巧

需要注意的是,在使用URLstartAccessingSecurityScopedResource()stopAccessingSecurityScopedResource()函数的时候,这个URL应该是沙盒传递过来的那个最原始的URL。如果你经过计算,使用了它内部的其它URL,那么在写入操作的时候,也必须调用原始的URL,而不能用计算的URL。如果你使用了后者,则操作不会成功。