Swift-将数据写入文档目录

28 阅读2分钟

之前我们研究了UserDefaults如何读取和写入数据,这对于用户设置或少量 JSON 非常有用,我们还研究了 SwiftData,当您需要对象之间的关系或更高级的排序和过滤。

现在,我们将考虑一个中间立场:我们将直接将数据写入文件。

事实上,所有应用程序都会有一个目录来存储我们想要的任何类型的文档。这里的文件会自动与 iCloud 备份同步,因此如果用户获得新设备,那么我们的数据将与所有其他系统数据一起恢复 - 我们甚至不需要考虑它。
所有 iOS 应用程序都是沙盒的,这意味着它们在自己的容器中运行,并且目录名称很难猜测。但我们可以依赖一个指向应用程序文档目录的特殊 地址:URL.documentsDirectory

该文档目录是我们的,我们可以在那里自由地读写文件。 因为它属于应用程序,如果应用程序本身被删除,它会自动删除。除了物理设备限制之外,我们可以存储的存储量没有限制,但请记住,用户可以使用“设置”应用程序查看您的应用程序占用了多少存储空间 。

为了写入数据,我们需要使用方法Data(contentsOf:)write(to:) 。这需要两个参数:

第一个可以通过将文档目录 URL 与文件名(例如 myfile.txt)组合来创建。

第二个,我更喜欢以数组的形式给它两个值:.atomic.completeFileProtection。他们做的事情非常不同,但都很重要:

  1. 要求原子保存意味着整个文件应该一次性写入。如果不包含此内容并且我们尝试写入一个大文件,则应用程序的另一部分可能会在文件仍在写入时尝试读取该文件。这不应该导致崩溃或其他任何问题,但这确实意味着它将仅读取部分数据,因为另一部分尚未写入。原子写入会导致系统将完整文件写入临时文件名(不是我们要求的文件名),完成后它会对目标文件名进行简单的重命名。这意味着要么整个文件都存在,要么什么都没有。
  2. 要求完整的文件保护意味着iOS会自动(并且透明地)加密文件,并且只允许我们的应用程序在设备解锁时读取它。 iOS 在保护用户数据安全方面做得很好,但额外安全也没有坏处!
func xxxx(){

    let data = Data("Test Message".utf8)

    let url = URL.documentsDirectory.appending(path: "message.txt")  

    do {

        try data.write(to: url, options: [.atomic, .completeFileProtection])

        let input = try String(contentsOf: url)

        print(input)

    } catch {

        print(error.localizedDescription)

    }  
}