Ios 在数组上使用NSUserDefaults
我正在尝试使用NSUserDefaults将数组保存到我的应用程序的核心数据中。我认为使用NSUserDefaults会很好,但问题是,无论我将创建默认值的代码放在哪里,它都会抛出SIGABRT错误 以下是创建默认值的代码:Ios 在数组上使用NSUserDefaults,ios,arrays,swift,swift2,nsuserdefaults,Ios,Arrays,Swift,Swift2,Nsuserdefaults,我正在尝试使用NSUserDefaults将数组保存到我的应用程序的核心数据中。我认为使用NSUserDefaults会很好,但问题是,无论我将创建默认值的代码放在哪里,它都会抛出SIGABRT错误 以下是创建默认值的代码: let levelArrayDefault = NSUserDefaults.standardUserDefaults() levelArrayDefault.setValue(levelsArray, forKey: "levelsArray") leve
let levelArrayDefault = NSUserDefaults.standardUserDefaults()
levelArrayDefault.setValue(levelsArray, forKey: "levelsArray")
levelArrayDefault.synchronize()
levelsArray是列表对象的数组:
class List: NSObject, NSCoding {
// MARK: Properties
var name: String
var AnswersArray = [Answer]()
init?(name: String) {
// Initialize stored properties.
self.name = name
if name.isEmpty {
return nil
}
}
required init(coder decoder: NSCoder){
self.AnswersArray = (decoder.decodeObjectForKey("AA") as? [Answer])!
self.name = (decoder.decodeObjectForKey("name") as? String)!
}
func encodeWithCoder(coder: NSCoder) {
if let AnswersArray = AnswersArray { coder.encodeObject(AnswersArray, forKey: "AA") }
if let name = name { coder.encodeObject(name, forKey: "name") }
}
}
class Answer: NSObject, NSCoding {
var EnglishAnswer: String = ""
var ChineseAnswer: String = ""
init(newEng: String, newChi: String){
self.EnglishAnswer = newEng
self.ChineseAnswer = newChi
}
required init(coder decoder: NSCoder){
self.EnglishAnswer = (decoder.decodeObjectForKey("EnglishAnswer") as? String)!
self.ChineseAnswer = (decoder.decodeObjectForKey("ChineseAnswer") as? String)!
}
func encodeWithCoder(coder: NSCoder) {
if let EnglishAnswer = EnglishAnswer { coder.encodeObject(EnglishAnswer, forKey: "EnglishAnswer") }
if let ChineseAnswer = ChineseAnswer { coder.encodeObject(ChineseAnswer, forKey: "ChineseAnswer") }
}
}
如何阻止SIGABRT弹出并存储阵列。
非常感谢您的帮助。如果您想将自定义对象保存在
NSUserDefaults
中,仅使类NSCoding
兼容是不够的——您必须将数据实际编码到NSData
对象中。这是一个常见的错误--请参阅以了解类似的情况
因此,您已将NSCoding
添加到答案
和列表
类中。这是一个好的开始。在继续之前,应使用NSKeyedArchiver
将包含几个Answer
对象的列表
对象的示例编码到NSData
的实例中,以验证该步骤是否正确,然后使用nskeyedunachiver
将该数据对象解码回您的列表中。验证您所关心的一切都能顺利完成往返。这将是一个使用Xcode测试工具的好地方——您可以编写一个单元测试,它完全符合我所描述的
一旦你知道你的NSCoding
功能正确,您应该修改代码,使其将您的列表编码为NSData
,并使用-setObject:forKey:
方法将结果数据对象存储在nsserdefaults
中。在将其存储为nsserdefaults之前,您需要使用NSKeyedArchiver将其转换为NSData,请尝试以下操作:
更新:Xcode 11.4•Swift 5.2或更高版本
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let list = List(name: "Student")
list.answers = [Answer(english: "english answer", chinese: "中文回答")]
let data = (try? NSKeyedArchiver.archivedData(withRootObject: [list], requiringSecureCoding: false)) ?? Data()
UserDefaults.standard.set(data, forKey: "listData")
guard
let loadedData = UserDefaults.standard.data(forKey: "listData"),
let loadedArray = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(loadedData) as? [List]
else { return }
print(loadedData.count)
print(loadedArray.first ?? "none")
print(loadedArray.first?.name ?? "no name")
print(loadedArray.first?.answers.first?.english ?? "no english")
print(loadedArray.first?.answers.first?.chinese ?? "no chinese")
}
}
仅供参考-使用setObject:forKey:
,而不是setValue:forKey:
。不能在用户默认设置中存储列表对象或列表对象数组。只有属性列表值是合法的。此外,您不能将自定义类存储到NSUserDefaults中。首先需要使用NSKeyedArchiver
将其转换为NSData
。请搜索堆栈溢出-在抛出sigabrt之前,在这个主题上存在许多问题error@needshelp编辑您的问题并更新代码OK。但是如果你不解释你所遇到的问题的本质,这里没有人能帮助你。
class Answer: NSObject, NSCoding {
let english: String
let chinese: String
init(english: String, chinese: String) {
self.english = english
self.chinese = chinese
}
required init(coder decoder: NSCoder) {
self.english = decoder.decodeString(forKey: "english")
self.chinese = decoder.decodeString(forKey: "chinese")
}
func encode(with coder: NSCoder) {
coder.encode(english, forKey: "english")
coder.encode(chinese, forKey: "chinese")
}
}
class List: NSObject, NSCoding {
let name: String
fileprivate var data = Data()
var answers: [Answer] {
get {
(try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)) as? [Answer] ?? []
}
set {
data = (try? NSKeyedArchiver.archivedData(withRootObject: newValue, requiringSecureCoding: false)) ?? Data()
}
}
init(name: String) {
self.name = name
}
required init(coder decoder: NSCoder) {
self.data = decoder.decodeData(forKey: "answersData")
self.name = decoder.decodeString(forKey: "name")
}
func encode(with coder: NSCoder) {
coder.encode(data, forKey: "answersData")
coder.encode(name, forKey: "name")
}
}
extension NSCoder {
func decodeString(forKey key: String) -> String {
return decodeObject(forKey: key) as? String ?? ""
}
func decodeData(forKey key: String) -> Data {
return decodeObject(forKey: key) as? Data ?? Data()
}
}