在从UserDefault检索对象数组时,出现了“键'root'的值为意外类'NSArray'”错误,Swift。

7

我正在尝试在Swift中检索自定义对象数组,但遇到错误。

"UserInfo={NSDebugDescription=value for key 'root' was of unexpected class 'NSArray'. Allowed classes are '{(MusicCloud.Playlist)}"

我的项目是一个音乐播放器,所以我有一个歌曲对象和一个播放列表对象,它们都有一个名称和歌曲列表。

我已经对对象模型进行了编码:

class Playlist: NSObject, NSCoding{
    var name: String
    var songs: [Song]
    var image: UIImage

    override init() {
        self.name = ""
        self.songs = []
        self.image = UIImage()
    }

    init(name: String, songs: [Song], image: UIImage) {
        self.name = name
        self.songs = songs
        self.image = image
    }

    required convenience init(coder aDecoder: NSCoder) {
        let name = aDecoder.decodeObject(forKey: "name") as! String
        let songs = aDecoder.decodeObject(forKey: "songs") as! [Song]
        let image = aDecoder.decodeObject(forKey: "photo") as! UIImage
        self.init(name: name, songs: songs, image: image)
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: "name")
        aCoder.encode(songs, forKey: "songs")
        aCoder.encode(image, forKey: "photo")
    }
}

存储播放列表:

let playlist: Playlist = Playlist(name: txt.text!, songs: [], image: UIImage())
            MusicService.shared.playlists.append(playlist)
            do{
                let encodedData: Data = try NSKeyedArchiver.archivedData(withRootObject: MusicService.shared.playlists, requiringSecureCoding: false)
                self.userDefaults.set(encodedData, forKey: "playlist")
                self.userDefaults.synchronize()
            }catch let error{
                print("error when add  \(error)")
            }

并且获取它:

do{
            let decodedPlaylists = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [Playlist.self], from: decoded!) as! [Playlist]
            print("here is decoded playlist: \(decodedPlaylists)")
            MusicService.shared.playlists = decodedPlaylists
        }catch let error{
            print("error when retrieve \(error)")
        }

完整错误描述:

Domain=NSCocoaErrorDomain Code=4864 "value for key 'root' was of unexpected class 'NSArray'. Allowed classes are '{(
    MusicCloud.Playlist
)}'."

请问有人能告诉我是否有遗漏的地方吗?非常感谢!


2
你不应该使用NSCoding,而应该使用Codable - Dávid Pásztor
@DávidPásztor,你能再解释一下吗?我对这种本地存储还很陌生,非常感谢。 - hrtlkr29
1
请参考这个这个答案来实现。NSCoding是将自定义对象保存到文件系统的传统方式,而Codable是一种新的、纯Swift的解决方案,更加类型安全,因此您应该使用它来替代传统的解决方案。 - Dávid Pásztor
@DávidPásztor 我会看看的。非常感谢! - hrtlkr29
2个回答

8
我不知道为什么,但从


的更改会导致某些网站的格式出现问题。
let decodedPlaylists = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [Playlist.self], from: decoded!) as! [Playlist]

to

let decodedPlaylists = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decoded!) as! [Playlist]

这将为我解决问题。所以我将在此关闭我的工单。如果您注意到了,谢谢!


1
.unarchiveTopLevelObjectWithData在iOS 12.0版本之后已被弃用,应使用.unarchivedObject来替代。 - YourManDan

3

试一下

let decodedPlaylists = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [Playlist.self, NSArray.self], from: decoded!) as! [Playlist]

我猜,

下面的解码代码包含了NSArray的数据结构。

let songs = aDecoder.decodeObject(forKey: "songs") as! [Song]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接