Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在数组上使用NSUserDefaults_Ios_Arrays_Swift_Swift2_Nsuserdefaults - Fatal编程技术网

Ios 在数组上使用NSUserDefaults

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

我正在尝试使用NSUserDefaults将数组保存到我的应用程序的核心数据中。我认为使用NSUserDefaults会很好,但问题是,无论我将创建默认值的代码放在哪里,它都会抛出SIGABRT错误

以下是创建默认值的代码:

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()
    }
}