ios - 在数组上使用 NSUserDefaults

标签 ios arrays swift swift2 nsuserdefaults

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

这是创建默认值的代码:

let levelArrayDefault = NSUserDefaults.standardUserDefaults()
    levelArrayDefault.setValue(levelsArray, forKey: "levelsArray")
    levelArrayDefault.synchronize()

levelsArray 是 List 对象的数组:

    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 之前,您需要使用 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")
    }
}
<小时/>
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()
    }
}

关于ios - 在数组上使用 NSUserDefaults,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41782323/

相关文章:

iOS 应用程序问题 - 如何解决?

ios - 我只想在我的应用程序中打开教程页面一次。如何做到这一点?

java - 循环/搜索数组直到特定索引

swift - UIView drawRect 仅在 UITableViewCell 中调用一次,导致在重新使用单元格时产生陈旧数据

ios - Swift 选择器和闭包讨论

ios - 如何在 iOS 9 中创建分享按钮?

ios - 设置 UITableViewController 的子类

c++ - 将二维数组作为参数传递

arrays - perl6 插入数组以匹配 AND、OR、NOT 函数

swift - SpriteKit 场景切换时的内存问题