📃 APFS - 苹果沙盒文件系统基础知识
2024/01/04Sandbox 沙盒目录
每个iOS应用程序在读写文件时都有自己的沙盒目录。出于安全考虑,iOS 应用与文件系统的每次交互都限制在这个沙盒目录中。例外情况是对用户数据(如照片、音乐、联系人等)的访问请求。
沙盒结构目录如下:
Bundle 容器目录(Bundle Container Directory):应用程序的 bundle 资源(xxx.app),包含了应用程序中所有资源文件,比如图片、字符串文件、本地化资源等等,它仅有读取的权限。
数据容器目录(Data Container Directory):用于保存应用程序和用户数据。目录分为:
Documents
- 用于存储用户生成的内容。Library
- 存储不应该暴露给用户的应用程序文件。tmp
- 临时文件,系统会定期清理这些文件。
Documents
文档目录,Apple 建议使用 Documents
存储用户生成的内容。这包括用户通过我们应用程序中产生(删除)的任何内容,比如文本文件、绘图、图片、视频文件等,可以添加子目录组织这些内容。
系统还会创建 Documents/Inbox
目录,可以使用它来访问其它应用程序要求打开的文件,在这里可以读取/删除该目录文件,但不能编辑/新增文件。
Library
Library 目录包含了两个标准子目录,用于存储应用程序的支持文件。
Library/Application Support/
- 用于存储应用程序的需要,但不应该暴露给用户的任何文件,比如配件文件、模板、数据文件等。Library/Caches
- 用于缓存可以重新创建,并且需要比tmp
目录的文件更持久的数据,系统可能在极少数情况下删除该目录以释放空间。
管理文件
访问 Bundle 资源:Foundation 框架提供了 Bundle 类型,可以直接定位资源。
// appConfig.json
let url = Bundle.main.url(forResource: "appConfig", withExtension: "json")
// 转换它
let data = try Data(contentsOf: url)
let configuration = try JSONDecoder().decode(ConfigurationModel.self, from: data)
数据容器目录中读写:为了管理 Documents 或 Library 目录中的文件,Foundation 框架提供了 FileManager 类型。
例如定位到 Library/Application Support
目录,可以执行以下操作:
let directoryURL = try FileManager.default.url(
for: .applicationSupportDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false
)
FileManager 参数中 for 枚举值:
.applicationSupportDirectory
==>"Library/Application Support"
.cachesDirectory
==>"Library/Caches"
.documentDirecotry
==>"Documents/"
🔥 另外,从 iOS16 开始,可以通过 URL 类型更加方便访问目录。
let url = URL.documentsDirectory // Documents/
let fileURL = URL.documentsDirecotry.appending(path: "myfile")
iOS16 后新增的 URL 常见静态属性有:
.applicationDirectory
.applicationSupportDirectory
🌟.cachesDirectory
🌟.documentsDirectory
🌟.libraryDirectory
🌟.temporaryDirectory
🌟.downloadsDirectory
.homeDirectory
.desktopDirectory
- .....
使用 FileManager 创建文件
let myDir = URL.applicationSupportDirectory.appending(path: "mydir")
try FileManager.default.createDirectory(
at: myDir,
withIntermediateDirectories: false,
attributes: nil
)
注意如果目录已经存在,上面代码会抛出错误。在创建目录之前先用 FileManager.fileExists(atPath:)
进行检查,或者错误捕获。
文件备份
如果用户已经打开了iCloud备份,Documents
和 Library/Application Support/
目录中的所有文件都会默认备份。
Apple 建议从备份中排除所有可以通过服务器重新下载创建的文件。
var resourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true
url.setResourceValues(resourceValues)
要从备份中排除一个URL,我们可以使用 URLResourceValues 类型,并将 isExcludedFromBackup
设置为 true
。