我在使用对象存档时遇到以下错误:“无法打开文件”users.archive“,因为没有这样的文件。

I encountered the following error when using object archiving : "The file “users.archive” couldn’t be opened because there is no such file."

提问人:zzhzzh 提问时间:11/17/2023 最后编辑:HangarRashzzhzzh 更新时间:11/17/2023 访问量:27

问:

详细例外情况:

2023-11-17 00:20:40.993562+0800 FriendCollege[80762:995113] [plugin] AddInstanceForFactory:没有注册 id <CFUUID 0x600000270640> F8BB1C28-BAE8-11D6-9C31-00039315CD46
错误域 = NSCocoaErrorDomain 代码 = 260 “无法打开文件”users.archive“,因为没有这样的文件。 UserInfo={NSFilePath=/Users/zhouzihao/Library/Developer/CoreSimulator/Devices/EB37A319-C800-4B6E-BF59-B9E3B50548FD/data/Containers/Data/Application/47DB7CC2-464B-4C84-AAFF-B881D5BC100D/Documents/users.archive, NSUnderlyingError=0x600000c7ad00 {Error Domain=NSPOSIXErrorDomain Code=2 “没有这样的文件或目录”}}

我的代码:

import UIKit

class UserInfo {
    
    static let userInfo = UserInfo()
    
    var UsersCollection = [User]()
    
    let archiveURL : URL = {
        let docDirs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let docDir = docDirs.first!
        return docDir.appendingPathComponent("users.archive", isDirectory: true)
    } ()
    
    
    init() {

        do {
            let data = try Data(contentsOf: archiveURL)
            if let sc = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) {
                    UsersCollection = sc as! [User]
            }
        } catch{
            print(error)
        }

    }
    
    func saveUser() {
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: UsersCollection, requiringSecureCoding: false)
            try data.write(to: archiveURL)
            print("successfully save")
        } catch {
            print(error)
        }
    }
}

事实上,我在另一个项目中使用了代码,除了变量的名称外,大致相似。所以我不知道为什么这是不对的。

SWIFT 存档

评论

1赞 HangarRash 11/17/2023
您的代码假定该文件存在。但是在全新安装该应用程序时,还没有文件。在第一次调用之前,它不会创建。saveUser()

答:

0赞 soundflix 11/17/2023 #1

有两件事需要改变:

  • 创建 URL 时,应为 .isDirectoryfalse
  • 正如@HangarRash所评论的,在首次运行时,尚未创建存档文件。

这是我的建议:

class UserInfo {
    
    static let shared = UserInfo()
    
    var usersCollection = [User]()
    
    let archiveURL: URL = {
        let docDirs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let docDir = docDirs.first!
        return docDir.appendingPathComponent("users.archive", isDirectory: false)
    } ()
    
    private init() {
        do {
            let data = try Data(contentsOf: archiveURL)
            if let sc = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) {
                usersCollection = sc as! [User]
            }
        } catch CocoaError.fileReadNoSuchFile {
            print("creating new empty archive file")
            saveUser()
        } catch {
            print(error)
        }
    }
    
    func saveUser() {
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: usersCollection, requiringSecureCoding: false)
            try data.write(to: archiveURL)
            print("successfully save")
        } catch {
            print(error)
        }
    }
}

像这样,在第一次运行时创建一个空文件。


与您的问题无关,请注意我更改的几件事:

我重命名了您的静态变量。这会导致对单例对象的调用更加清晰:

let userInfo = UserInfo.shared

添加到单例对象的启动器可确保它实际上只能实例化一次。private

我根据 Swift 中的命名约定重命名为 ,(实例 <-> 类型)。UsersCollectionusersCollection

评论

0赞 HangarRash 11/18/2023
进一步的建议:支持安全编码并使用不推荐使用的方法。也没有理由从 .默认为空数组就足够了。我也会避免在 中使用 .您有一个 .为了安全起见,请使用可选的铸件。NSKeyedUnarchiversaveUserinitusersCollectionas!initif letif let