我们什么时候应该使用 FileManager.default.urls 而不是 NSSearchPathForDirectoriesInDomains?

Che*_*eng 3 ios swift

目前,如果我想在文档目录中创建目录层次结构,我将执行以下操作

\n
\n

使用 NSSearchPathForDirectoriesInDomains (工作正常)

\n
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)\nlet documentsDirectory = paths[0]\nlet documentUrl1 = URL(string: documentsDirectory)!\n//\n// /Users/yccheok/Library/Developer/...\n//\nprint("documentUrl1 -> \\(documentUrl1)")\n\nlet dataPath = documentUrl1.appendingPathComponent("SubFolder1").appendingPathComponent("SubFolder2")\nprint("dataPath.absoluteString -> \\(dataPath.absoluteString)")\nif !FileManager.default.fileExists(atPath: dataPath.absoluteString) {\n    do {\n        try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: true, attributes: nil)\n        print("Folder creation done!")\n    } catch {\n        print(error.localizedDescription)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

但是,如果我使用以下

\n

使用 FileManager.default.urls (不起作用)

\n
let documentUrl0 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]\n//\n// file:///Users/yccheok/Library/Developer/...\n//\nprint("documentUrl0 -> \\(documentUrl0)")\n\nlet dataPath = documentUrl0.appendingPathComponent("SubFolder1").appendingPathComponent("SubFolder2")\nprint("dataPath.absoluteString -> \\(dataPath.absoluteString)")\nif !FileManager.default.fileExists(atPath: dataPath.absoluteString) {\n    do {\n        try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: true, attributes: nil)\n        print("Folder creation done!")\n    } catch {\n        print(error.localizedDescription)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

将打印以下错误

\n
\n

您无法\xe2\x80\x99t 保存文件\xe2\x80\x9cSubFolder2\xe2\x80\x9d,因为该卷是只读的。

\n
\n
\n

我想知道,在什么用例下,这FileManager.default.urls会有用?谢谢。

\n

vad*_*ian 6

URL(stringabsoluteString是处理文件系统路径的错误 API。

您的代码意外地起作用,因为URL(string应用于路径会创建路径而不是有效的 URL,并且absoluteString应用于路径会返回路径,因为没有方案 ( file://)。

但是,强烈建议您不要这样做。必须使用文件系统 URL 创建,URL(fileURLWithPath并且您可以使用该属性获取路径path

我们鼓励您使用该FileManagerAPI,因为它提供了更好的错误处理,并且还提供了与 URL 相关的 API,该 API 优于字符串路径 API。

FileManager如果目录不存在,这是创建目录的正确方法

let fm = FileManager.default
do {
    let documentUrl = try fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    //
    // file:///Users/yccheok/Library/Developer/...
    //
    print("documentUrl -> \(documentUrl)")
    
    let dataURL = documentUrl.appendingPathComponent("SubFolder1").appendingPathComponent("SubFolder2")
    print("dataPath.path -> \(dataURL.path)")
    if !fm.fileExists(atPath: dataURL.path) {
        try fm.createDirectory(at: dataURL, withIntermediateDirectories: true, attributes: nil)
        print("Folder creation done!")
    }
} catch { print(error) }
Run Code Online (Sandbox Code Playgroud)

在 iOS 16+、macOS 13+ 中您可以替换

let documentUrl = try fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
...
let dataURL = documentUrl.appendingPathComponent("SubFolder1").appendingPathComponent("SubFolder2")
Run Code Online (Sandbox Code Playgroud)

let documentUrl = URL.documentsDirectory
...
let dataURL = documentUrl.appending(components: "SubFolder1", "SubFolder2")
Run Code Online (Sandbox Code Playgroud)