如何使用UserDefaults.standard保存自定义数据?

How to use UserDefaults.standard save custom Data?

我的数据Class

import Foundation

class People {

let peopleImage : String
let peopleTime : Int
let peopleName : String

init(image:String, second:Int, name:String) {

    peopleImage = image
    peopleTime = second
    peopleName = name

}

我的数据列表文件

import Foundation

class CustomPeopleList {

    var peopleList = [

        People(image: "Man", second: 12, name: "Andy"),
        People(image: "Woman", second: 60, name: "Kevin"),



    ]

}

我的 viewController :

let defaults = UserDefaults.standard    
var allPeopleList = CustomPeopleList

有一个按钮,当我点击按钮时,它会删除数据列表中的第一项,但我发现它总是错误。我的用户默认代码是这样的:

self.allPeopleList.remove(at: indexPathTimer.row)
let aaa = self.allPeopleList
let newPeopleData = NSKeyedArchiver.archivedData(withRootObject: self.allPeopleList)
self.defaults.set(aaa, forKey: "myPeopleData")

当我想使用它时

if let peopleData = defaults.data(forKey: "myPeopleData") as? [People] {
allPeopleList = peopleData
}
var allPeopleList = NSKeyedUnarchiver.unarchiveObject(with: peopleData!) as? [Peoples]

xcode说错了

使用NSKeyedUnarchiverNSKeyedArchiver.

时,需要从NSObject继承Peopleclass

要在用户默认值中存储自定义对象,您需要继承自定义 class 形式 NSObject 否则您将获得运行时 error/crashes.

class People: NSObject {


}

我推荐Codable协议并将数据保存为JSON。它 比 Obj-C 相关 NSKeyed(Un)Archiver

更快
  • 采纳协议

    class People : Codable {
    
  • 将数组编码为JSON并保存

    do {        
       let newPeopleData = try JSONEncoder().encode(self.allPeopleList)
       self.defaults.set(newPeopleData, forKey: "myPeopleData")
    } catch { print(error)
    
  • 读取数据也很简单

    do {
       if let newPeopleData = self.defaults.data(forKey: "myPeopleData") {
          allPeopleList = try JSONDecoder().decode([People].self, from: newPeopleData)
       }
    } catch { print(error)
    

注意:我将 class 命名为单数形式 Person,因为一组人 ([People]) 是重言式的,并且将属性命名为 imagetimename.

如果您使用 NSKeyedArchiverNSKeyedUnarchiver,那么您归档的对象必须是 NSObject 的子类并符合 NSCoding.

你必须这样做:

class People: NSObject, NSCoding {

    let peopleImage : String
    let peopleTime : Int
    let peopleName : String

    init(image:String, second:Int, name:String) {
        peopleImage = image
        peopleTime = second
        peopleName = name
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        self.peopleImage = aDecoder.decodeObject(forKey: "peopleImage") as! String
        self.peopleTime = aDecoder.decodeInteger(forKey: "peopleTime")
        self.peopleName = aDecoder.decodeObject(forKey: "peopleName") as! String
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.peopleImage, forKey: "peopleImage")
        aCoder.encode(self.peopleTime, forKey: "peopleTime")
        aCoder.encode(self.peopleName, forKey: "peopleName")
    }
}

class CustomPeopleList: NSObject, NSCoding {

    var peopleList = [
        People(image: "Man", second: 12, name: "Andy"),
        People(image: "Woman", second: 60, name: "Kevin"),
    ]

    override init() {
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        self.peopleList = aDecoder.decodeObject(forKey: "peopleList") as! [People]
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.peopleList, forKey: "peopleList")
    }

}

var allPeopleList = CustomPeopleList()

let data = NSKeyedArchiver.archivedData(withRootObject: allPeopleList)

不过

实施 NSCoding 可能会非常冗长。

如果您的对象包含基本实体,例如整数、字符串和 arrays/dictionaries 可编码实体,那么使用 Swift 的新 Codable 协议可能更容易。

这种方法的优点是,如果你的对象很简单,那么Swift可以为你生成编码和解码方法。

个人推荐Codable。它可以比旧的 NSCoding 方法简单得多。

看起来像这样:

class People: Codable {

    let peopleImage : String
    let peopleTime : Int
    let peopleName : String

    init(image:String, second:Int, name:String) {
        peopleImage = image
        peopleTime = second
        peopleName = name
    }
}

class CustomPeopleList: Codable {

    var peopleList = [
        People(image: "Man", second: 12, name: "Andy"),
        People(image: "Woman", second: 60, name: "Kevin"),
    ]

}

var allPeopleList = CustomPeopleList()

// Can save in whatever format you want. JSON is always light and simple.
let data = try JSONEncoder().encode(allPeopleList)

// Decode the data object later.
let decodedPeopleList = try JSONDecoder().decode(CustomPeopleList.self, from: data)