我的数据类
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
有一个按钮,当我点击按钮时它会删除数据列表中的第一个项目,但我发现它总是错误的。我的userdefault代码是这样的:
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说错了
答案 0 :(得分:1)
我推荐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)
注意:我会以单数形式Person
命名该课程,因为人物数组([People]
)具有重言性并且可以命名属性image
,time
和name
。
答案 1 :(得分:1)
如果您使用的是NSKeyedArchiver
和NSKeyedUnarchiver
,那么您归档的对象必须是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
可能非常详细。
如果您的对象包含基本实体,如整数,字符串和可编码实体的数组/字典,那么使用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)
答案 2 :(得分:0)
当您使用NSKeyedUnarchiver
或NSKeyedArchiver
时,您需要从NSObject继承NSObject
类。
要在userdefaaults中存储自定义对象,您需要继承自定义类窗体class People: NSObject {
}
,否则会出现运行时错误/崩溃。
function replacement() {
// For testing purposes, I created a spreadsheet that has data where
// your original code expects it. I'm not sure if this is actually all
// in one spreadsheet or maybe spread across multiple, since you didn't
// specify.
var formularz = SpreadsheetApp.getActiveSpreadsheet();
var total = formularz.getSheetByName('total');
var wysylka = formularz.getSheetByName('wysylka');
// CONFIGURATION
// These are constants to capture the script configuration that can be
// easily tweaked without diving into the code.
// 0-based index of the first data sheet.
var START_SHEET = 1;
// 0-based index of the last data sheet.
// NOTE: I only populated 3 data sheets in my test environment.
var END_SHEET = 3;
// 0-based index of the row with sheet data within the total sheet.
var TOTAL_STARTING_ROW = 16;
// 0-based index of the column with sheet data within the total sheet.
var TOTAL_COLUMN = 4;
// 0-based index of the starting row within data sheets.
var DATA_STARTING_ROW = 7;
// 0-based index of the 'KOD' column within data sheets.
var DATA_KOD_COLUMN = 2;
// 0-based index of the 'il' column within data sheets.
var DATA_IL_COLUMN = 7;
// END OF CONFIGURATION
// A prerequisite calculation based on the configuration.
var numSheets = END_SHEET - START_SHEET + 1;
// Use a single getValues() call to fetch all necessary total data.
totalData = total.getRange(TOTAL_STARTING_ROW + 1, TOTAL_COLUMN + 1, numSheets).getValues();
// Use an array to capture all of the rows we will append to the 'wysylka' sheet.
var wysylkaRows = [];
for (var i = 0; i < numSheets; i++) {
// Use a single getValues() call to fetch all necessary data from the data sheet.
// Using getDataRange() to get all sheet data, instead of manually keeping track
// of number of rows per sheet.
var sheetData = formularz.getSheets()[START_SHEET + i].getDataRange().getValues();
for (var j = DATA_STARTING_ROW; j < sheetData.length; j++) {
if (totalData[i][0] > 1) {
if (sheetData[j][DATA_IL_COLUMN] > 0) {
// Push an array that represents a row we'll add to the 'wysylka' sheet.
wysylkaRows.push([
sheetData[j][DATA_KOD_COLUMN],
sheetData[j][DATA_IL_COLUMN]
]);
}
}
}
}
// Get a range for all of the accumulated rows.
appendRange = wysylka.getRange(wysylka.getLastRow() + 1, 1,
wysylkaRows.length, wysylkaRows[0].length);
// Set all rows with a single setValues() call.
appendRange.setValues(wysylkaRows);
}