【翻译】如何在 iOS 16 中获取系统文件夹的 URL

Posted by beforeold on October 6, 2022

翻译自原文:Get URLs for system folders in iOS 16

在 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