在 iOS 16 中处理文件和文件夹变得容易多了。之前,为了获取一个应用文件夹下的某个文件的路径,不得不使用一些相当繁琐的 FileManager
API。现在,可以直接从 URL
扩展的静态属性中获取到系统文件夹的路径了。
举个例子,为了获取应用沙盒中的 documents
文件夹,可以读取 URL.documentsDirectory 属性。
let url = URL.documentsDirectory
同样也可以很容易地获取到其他系统文件夹的 URL。可以参考 URL struct 的官方文档的 type properties 部分列出的全部选项。
另一项重大的提升是新增了 appending(path:directoryHint:) 方法,用来取代旧的 appendingPathComponent(_:isDirectory:) 方法。为了判断路径是否为文件夹,新的方法接受一个 DirectoryHint 参数,用来指示 Foundation
是否应该执行一次文件系统检查。该参数的默认值是 inferFromPath,意味着将通过传入的路径参数字符串自行进行推导后判断。即,如果路径字符串包含了斜杠 “/“,则会被视作文件夹。
在 iOS 16 之前,要么传一个 isDirectory
布尔值给 appendingPathComponent(_:isDirectory:)
方法,要么调用 appendingPathComponent(_:) 不带布尔值参数的方法。后者将执行一次文件系统操作来决定路径是否为文件夹。使用 iOS 16 的新 API ,可以轻松地避免旧方法可能带来的性能损耗。
现在要构造一个文件的 URL,只需要简单地写 url.appending(path: "myfile”)
即可。Foundation
框架会从 path
参数推导出该路径不是文件夹,因为它没有以斜杠 “/” 结尾,也不会进行一次不必要的文件系统检查。
得益于这些优化,在 iOS 16 中可以通过一行简单的代码即可获取一个 documents
文件夹下的文件 URL:
// iOS 16 example
let fileURL = URL.documentsDirectory
.appending(path: "myfile")
这是自 iOS 15 以来一次令人激动的更新,那时候为了获取同样的结果还需要更多冗长的 FileManager
API:
// iOS 15 example
let fileURL = try FileManager.default
.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false
)
.appendingPathComponent(
"myfile", isDirectory: false
)
译者注:为了在 iOS 16 之前使用这些 type properties,尝试对相应的属性进行了自定义的扩展实现,并编写通过了单元测试,代码见GitHub => SwiftSugar => URL+Sugar