【问题标题】:Saving dictionary into NSUserDefaults将字典保存到 NSUserDefaults
【发布时间】:2014-08-03 22:42:34
【问题描述】:
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 中,您可以填写一些文本字段,最后按下 UIBarButtonItem。从 textFields 的数据中,创建类“Element”的新实例并将其添加到“newElement”属性之一的键处的“theDict”中。当我使用控制台输出检查它时,一切正常,但我最终无法将编辑后的字典保存在 userDefaults 中。没有语法错误,但是当我使用该应用程序并尝试通过第二个 viewController 向 Dictionary 添加另一个元素时,会显示以下错误:

错误消息:

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

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

编辑

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
}

}

【问题讨论】:

    标签: swift xcode6


    【解决方案1】:

    来自NSUserDefaults documentation

    value参数只能是属性列表对象:NSData, NSString、NSNumber、NSDate、NSArray 或 NSDictionary。对于 NSArray 和 NSDictionary 对象,它们的内容必须是属性列表对象。 参见Property List Programming Guide 中的“What is a Property List?”

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

    一种选择是确保Element 实现NSCoding protocol,然后使用NSKeyedArchiver 将您的字典转换为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)
    

    您的协议实现如下所示:

    init(coder aDecoder: NSCoder!) {
        self.state = State.fromRaw(aDecoder.decodeObjectForKey("state") as String)
    }
    
    func encodeWithCoder(aCoder: NSCoder!) {
        aCoder.encodeObject(self.state.toRaw(), forKey: "state")
    }
    

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

    【讨论】:

    • 非常感谢。但由于我对 iOS 开发人员真的很陌生,我似乎无法正确实现这个协议。请您看一下我上面的问题所附的尝试
    • @NickPodratz 您在实施协议时遇到了什么错误/问题?
    • state = State.fromRaw(aDecoder.decodeObjectForKey("state") as String)!这样就可以了。但是最初的错误消息仍然存在,应用程序崩溃了。
    • 你必须与@objc桥接,见stackoverflow.com/questions/24659609/…
    • 备注:Enum 的原始表示并不总是字符串。
    猜你喜欢
    • 2016-11-12
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多