将字典保存到 NSUserDefaults [英] Saving dictionary into NSUserDefaults

查看:37
本文介绍了将字典保存到 NSUserDefaults的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class AddElementVC: UIViewController {

    // textfields and some other functions are defined here 

    @IBAction func addElement(sender: UIBarButtonItem) {

        let newElement = Element(/* properties are defined here */)
        var theDict = NSUserDefaults.standardUserDefaults().dictionaryForKey(tableViewData) as [String: [Element]]

        if var theArray = theDict[newElement.someProperty] {
            theArray += newElement
            theDict[newElement.someProperty] = elementArray
        } else{
            theDict[newElement.someProperty] = [newElement]
        }

        NSUserDefaults.standardUserDefaults().setObject(theDict, forKey: tableViewData)

    }
}

对上述代码的解释:

我的 tableView-app 从 [String: [Element]] 类型的字典(Element 是一个自定义类)接收数据,该字典是从 userDefaults 加载的.在第二个 viewController 中,您可以填写一些 textFields,最后按下 UIBarButtonItem.根据 textFields 的数据,创建了类Element"的新实例,并将其添加到theDict"中newElement"属性之一的键处.当我使用控制台输出检查它时,一切正常,但我最终无法将编辑过的字典保存在 userDefaults 中.没有语法错误,但是当我使用该应用程序并尝试通过第二个 viewController 将另一个元素添加到 Dictionary 时,会显示以下错误:

My tableView-app receives its data from a dictionary of type [String: [Element]] (Element is a custom class), which is loaded from the userDefaults. In a second viewController you can fill out some textFields and finally press a UIBarButtonItem. From the textFields' data a new instance of the class "Element" is created and added to "theDict" at the key of one of the "newElement"'s properties. All that works fine as I checked it with console-outputs, but I am not able to finally save the edited dictionary in the userDefaults. There are no syntax-errors, but when I use the app and try to to add another element to the Dictionary via the second viewController, the following error is displayed:

错误消息:

NSForwarding: 警告: '_TtC12myApp7Element' 类的对象 0xdcb002c 没有实现 methodSignatureForSelector: -- 麻烦提前

NSForwarding: warning: object 0xdcb002c of class '_TtC12myApp7Element' does not implement methodSignatureForSelector: -- trouble ahead

研究并没有帮助我理解错误信息.

Researches didn't help me to understand the error-message.

编辑

import Foundation

class Element: NSCoding {

enum State: String {
    case state1 = "state1"
    case state2 = "state2"
}

let state: State
// some more properties

init(state: String /* something more */ ){
    self.state = State.fromRaw(state)!
    // something more
}

init(coder aDecoder: NSCoder!) {
    self.state = aDecoder.decodeObjectForKey("state") // displays error: 'AnyObject' is not convertible to 'Element.State'
    // something more
}

func encodeWithCoder(aCoder: NSCoder!) {
    aCoder.encodeObject(self.state, forKey: "state") // displays error: Extra Argument 'forKey' in call
    // something more
}

}

推荐答案

来自 NSUserDefaults 文档:

value 参数只能是属性列表对象:NSData,NSString、NSNumber、NSDate、NSArray 或 NSDictionary.对于 NSArray 和NSDictionary 对象,它们的内容必须是属性列表对象.参见 什么是属性列表?"//apple_ref/doc/uid/10000048i" rel="noreferrer">属性列表编程指南.

The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects. See "What is a Property List?" in Property List Programming Guide.

您不能在字典中存储包含 Element 元素的字典.

You cannot store a dictionary with elements of Element in the dictionary.

一种选择是确保 Element 实现 NSCoding 协议 然后使用 NSKeyedArchiver 将您的字典转换为 NSData:

One option is to make sure Element implements the NSCoding protocol and then use NSKeyedArchiver to convert your dictionary into NSData:

// Storing the dictionary
var data = NSKeyedArchiver.archivedDataWithRootObject(theDict)
NSUserDefaults.standardUserDefaults().setObject(data, forKey: tableViewData)

// Retrieving the dictionary
var outData = NSUserDefaults.standardUserDefaults().dataForKey(tableViewData)
var dict = NSKeyedUnarchiver.unarchiveObjectWithData(outData)

您的协议实现看起来像这样:

Your protocol implementation would look like something like this:

init(coder aDecoder: NSCoder!) {
    self.state = State.fromRaw(aDecoder.decodeObjectForKey("state") as String)
}

func encodeWithCoder(aCoder: NSCoder!) {
    aCoder.encodeObject(self.state.toRaw(), forKey: "state")
}

您不能存储枚举,但可以存储它的原始表示形式,即字符串.

You cannot store an Enum, but you can store the raw representation of it which is a string.

这篇关于将字典保存到 NSUserDefaults的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆