从 FileManager 中获取 "The file couldn’t be opened because there is no such file" 错误,即使它实际上已打开

Getting "The file couldn’t be opened because there is no such file" error from FileManager even though it's actually opened

我正在检索一个 plist 文件,更新它,然后将它写入磁盘。

1) 检索

func pListURL() -> URL? {
     guard let result = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("somePlist.plist") else { return nil }
     return result
 }

2) 更新

var data: [String: Int] = [:]
if let url = pListURL() {
    do {
        let dataContent = try Data(contentsOf: url)
        if let dict = try PropertyListSerialization.propertyList(from: dataContent, format: nil) as? [String: Int] {
            data = dict
        }
    } catch {
        print(error)
    }
}

// update code

3) 写入

if let path = pListURL() {
    do {
        let plistData = try PropertyListSerialization.data(fromPropertyList: data, format: .xml, options: 0)
        try plistData.write(to: path)
    } catch {
        print(error)
    }
}

奇怪的是我收到一条错误消息:

The file “somePlist.plist” couldn’t be opened because there is no such file.

尽管当我检查 plist 时,它实际上已按应有的方式正确创建和更新。据我所知,FileManager.default.url(for:in:appropriateFor:create: )create 参数确保它“创建目录,如果它不存在”,这意味着如果 plist 不存在,则创建 somePlist.plist已经存在。

As far as I know, the create parameter of FileManager.default.url(for:in:appropriateFor:create: ) ensures that it "creates the directory if it does not already exist", which means somePlist.plist is created if plist doesn't exist already.

不,这意味着 目录 已创建,但 文件 创建。

update 部分忽略 couldn’t be opened 错误并将(新)数据写入磁盘或检查文件是否存在 fileExists(atPath.

并且您可以将 pListURL 中的 return 值声明为 non-optional。确保文件夹 Documents 存在

func pListURL() -> URL {
     return try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("somePlist.plist")
}

更新:

这些是 updatewrite

的可靠版本
func update(dictionary: [String:Int]) {
    let url = pListURL()
    guard FileManager.default.fileExists(atPath: url.path) else { write(dictionary: dictionary); return }
    do {
        let dataContent = try Data(contentsOf: url)
        if var dict = try PropertyListSerialization.propertyList(from: dataContent, format: nil) as? [String: Int] {
            for (key, value) in dictionary {
                dict.updateValue(value, forKey: key)
            }
            write(dictionary: dict)
        } else {
            write(dictionary: dictionary)
        }
    } catch {
        print(error)
    }
}

func write(dictionary: [String:Int]) {
    let url = pListURL()
    do {
        let plistData = try PropertyListSerialization.data(fromPropertyList: dictionary, format: .xml, options: 0)
        try plistData.write(to: url)
    } catch {
        print(error)
    }
}