【问题标题】:Having Issue with store non property object存储非属性对象有问题
【发布时间】:2017-06-15 10:29:52
【问题描述】:

我正在尝试使用 UserDefaults 保存自定义文件,但我的应用程序由于以下原因崩溃:

致命错误:在展开可选值时意外发现 nil

这是我的代码,在我的自定义类中我声明了一个空数组

class AppDefualts: NSObject {

    var downloadedURLArray = [DownloadFile]() //Declare an empty array


    override init() {
        super.init()


        downloadedURLArray = loadStoredURL()
     }


//Store data
func addStored(file:DownloadFile) {

    //Add URL to array and save it
    downloadedURLArray.append(file)

    let data = NSKeyedArchiver.archivedData(withRootObject: downloadedURLArray)
    UserDefaults.standard.set(data, forKey: "storedURL")
}

 //Load:
    func loadStoredURL() -> Array<DownloadFile> {

        let data = UserDefaults.standard.data(forKey: "storedURL")
        downloadedURLArray = NSKeyedUnarchiver.unarchiveObject(with: data!) as? [DownloadFile] ?? [DownloadFile]()
        return downloadedURLArray

    }

任何帮助都会很棒

编辑 1: 我添加了NSCoding 协议:

func encode(with aCoder: NSCoder) {
    aCoder.encode(downloadedURLArray, forKey: "storedURL")
}

required init?(coder aDecoder: NSCoder) {
    downloadedURLArray = aDecoder.decodeObject(forKey: "storedURL") as! [DownloadFile]
}

现在应用程序因此而崩溃:

* 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“* -encodeObject:forKey: 无法发送到 NSCoder 类的抽象对象:创建一个 具体实例!'

【问题讨论】:

  • 阅读数据存储指南。你试图做的完全是错误的。

标签: ios arrays iphone swift xcode


【解决方案1】:

如果您想将自定义对象存储在UserDefault 中,那么您必须进行编码/解码。您的自定义对象应该确认NSCoding 协议。

存储到 UserDefault :您必须将对象转换为 NSData 并使用 NSKeyedArchiver 将它们存储到 UserDefault

从 UserDefault 获取:USerDefault 获取 NSData 并使用 NSKeyedUnArchiver 转换为自定义对象

参考convert custom object into NSData and vice versa的链接

示例:确认 NSCoding 协议的自定义对象

class Book: NSObject, NSCoding {
    var title: String
    var author: String
    var pageCount: Int
    var categories: [String]
    var available: Bool

    // Memberwise initializer
    init(title: String, author: String, pageCount: Int, categories: [String], available: Bool) {
        self.title = title
        self.author = author
        self.pageCount = pageCount
        self.categories = categories
        self.available = available
    }

    // MARK: NSCoding

    required convenience init?(coder decoder: NSCoder) {
        guard let title = decoder.decodeObjectForKey("title") as? String,
            let author = decoder.decodeObjectForKey("author") as? String,
            let categories = decoder.decodeObjectForKey("categories") as? [String]
            else { return nil }

        self.init(
            title: title,
            author: author,
            pageCount: decoder.decodeIntegerForKey("pageCount"),
            categories: categories,
            available: decoder.decodeBoolForKey("available")
        )
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encodeObject(self.title, forKey: "title")
        coder.encodeObject(self.author, forKey: "author")
        coder.encodeInt(Int32(self.pageCount), forKey: "pageCount")
        coder.encodeObject(self.categories, forKey: "categories")
        coder.encodeBool(self.available, forKey: "available")
    }
}

【讨论】:

  • 我做了同样的事情,使用NSKeyedArchiver 存储数据并使用NSKeyedUnarchiver 加载它你读过我的代码吗?
  • @Mc.Lover 但是您的自定义对象未确认 NSCoding 协议
  • @Mc.Lover 我已经用确认 NSCoding 协议的示例类更新了我的答案
  • 我想我需要创建一个与这个类分开的自定义类,我会尝试一下
  • @Mc.Lover AppDefualts 类编码/解码是正确的。您可以添加 DownloadFile 类代码吗?您还必须在 DownloadFile 类中确认 NSCoding 协议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2021-06-06
  • 2013-07-08
  • 2011-02-04
  • 1970-01-01
  • 2021-07-18
相关资源
最近更新 更多