在Swift </string,>中的NSUserDefaults中存储Dictionary <string,customobject =“”>

时间:2014-08-23 15:47:01

标签: dictionary struct swift nsuserdefaults

我已经创建了Dictionary,其中密钥为String且值为SectorCoordinate.的自定义对象 我只想在NSUserDefaults中存储完整的东西,但是当我这样做时,Xcode说:

The type [String, SectorCoordinate] does not conform to protocol AnyObject

我真的很困惑。我认为AnyObject是Swift的Objective-C id版本,应该能够容纳任何对象。

我已经看到并试图实施一系列针对[String: String]词典(例如JSON操作)的解决方案,但这些解决方案没有效果,但有类似的错误。我甚至试图分解键值对,并且在尝试存储一个SectorCoordinate(它本身只是一个struct并且有一堆String时,我也会遇到同样的错误} s,Int和其中的日期)为AnyObject

有没有人对如何将半复杂对象和/或其词典存储为AnyObject有任何建议?看起来这应该简单得多。

4 个答案:

答案 0 :(得分:2)

关于NSUserdefaults setObject:forKey:方法的Apple documentation州:

  

value参数只能是属性列表对象:NSData,   NSString,NSNumber,NSDate,NSArray或NSDictionary。对于NSArray和   NSDictionary对象,其内容必须是属性列表对象。   请参阅“属性列表编程指南”中的“什么是属性列表?”。

因此,例如,您可以将Swift Dictionary [String : NSNumber]强制转换为NSDictionary并使用NSUserDefaults保存/检索它,如下所示:

let dictionary = ["myKey" : NSNumber(int: 12)] as NSDictionary
NSUserDefaults.standardUserDefaults().setObject(dictionary, forKey: "myDict") //[myKey : 12]
NSUserDefaults.standardUserDefaults().dictionaryForKey("myDict") //{[myKey : 12]}

但对于[String : SectorCoordinate]类型的Swift词典来说,这是不可能的,其中SectorCoordinate是Swift Struct。

答案 1 :(得分:2)

您可以在NSUserDefs中存储任何对象,请参阅NSUserDefaults Apple文档:

  

NSUserDefaults类提供了便于访问的方法   常见类型,例如浮点数,双精度数,整数,布尔值和URL。一个   默认对象必须是属性列表,即(或   对于集合的实例组合):NSData,NSString,   NSNumber,NSDate,NSArray或NSDictionary。 如果你想存储任何   在其他类型的对象中,通常应将其存档以创建   NSData的实例。有关更多详细信息,请参阅首选项和设置   编程指南。

要拥有一个可以无缝转换为NSData的对象,请确保您的类符合NSCoding协议(即可以归档和取消归档)。 Swift有时也希望你的类符合NSSecureCoding。

答案 2 :(得分:1)

我已经回答了如何在本页的其他地方使用NSUserDefaults,但如果您有任何数据,请不要使用NSUserDefaults。此版本将包含您自己的自制结构的字典数组保存到FILE并恢复它们。这可以粘贴到游乐场进行测试。事实上,在NSUserDefaults版本中,另外两个支票簿条目会使用户默认值中的保存崩溃。

import Cocoa

//The key to the dictionary is in the struct here as permanentTimeDateCode

struct CheckBookEntry{

    var permanentTimeDateCode = String()  //value here is also the key for the dictorary it must be a string
    var amountOfTransaction = Double()
    var category = String()
    var payee = String()
    var memo = String()
    var checkNumber = String()

}

var checkBookEntryOne = CheckBookEntry(permanentTimeDateCode: "2015-02--06", amountOfTransaction: 20.00, category: "Properietor", payee: "Balance Forward", memo: "No memo", checkNumber: "00000")

var checkBookEntryTwo = CheckBookEntry(permanentTimeDateCode: "2015-02--05", amountOfTransaction: -15.00, category: "Reference", payee: "Bookstore", memo: "No memo", checkNumber: "00001")

var checkBookEntryThree = CheckBookEntry(permanentTimeDateCode: "2015-02--08", amountOfTransaction: -5.00, category: "Dinning", payee: "Moe's", memo: "Good Eats", checkNumber: "00003")

//A dictionary with the date as the key and a CheckBookEntry struct as the value.
var myCheckBookEntry:Dictionary = [String  :CheckBookEntry ]()

myCheckBookEntry["2015-02--06"] = checkBookEntryOne
myCheckBookEntry["2015-02--07"] = checkBookEntryTwo
myCheckBookEntry["2015-02--08"] = checkBookEntryThree
print(myCheckBookEntry)


//To save these set up an array of dictionaries
var checkEntryArrayOfDictionaries:[[String:AnyObject]] = []

//your struct is no an object that can be saved so it needs to be converted.
//use the variable names from our struct CheckBookEntry as the keys

checkEntryArrayOfDictionaries.append( ["permanentTimeDateCode" : checkBookEntryOne.permanentTimeDateCode,  "amountOfTransaction" : checkBookEntryOne.amountOfTransaction, "catergory" : checkBookEntryOne.category, "payee" : checkBookEntryOne.payee, "memo" :  checkBookEntryOne.memo, "checkNumber": checkBookEntryOne.checkNumber])

checkEntryArrayOfDictionaries.append( ["permanentTimeDateCode" : checkBookEntryTwo.permanentTimeDateCode,  "amountOfTransaction" : checkBookEntryTwo.amountOfTransaction, "catergory" : checkBookEntryTwo.category, "payee" : checkBookEntryTwo.payee, "memo" :  checkBookEntryTwo.memo, "checkNumber": checkBookEntryTwo.checkNumber])

checkEntryArrayOfDictionaries.append( ["permanentTimeDateCode" : checkBookEntryThree.permanentTimeDateCode,  "amountOfTransaction" : checkBookEntryThree.amountOfTransaction, "catergory" : checkBookEntryThree.category, "payee" : checkBookEntryThree.payee, "memo" :  checkBookEntryThree.memo, "checkNumber": checkBookEntryThree.checkNumber])


print("//______________printing checkEntryArrayOfDictionaries----//")
print(checkEntryArrayOfDictionaries)

//Save The values
NSUserDefaults().setObject(checkEntryArrayOfDictionaries, forKey: "aCheckbook")

let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let pathLocationString:String =  paths[0] as String

let checkbookFile:String = pathLocationString.stringByAppendingString("/aCheckbook")
print(checkbookFile)

if !NSFileManager.defaultManager().fileExistsAtPath(checkbookFile) {

    print("files exists or will exist")
    NSFileManager.defaultManager().createFileAtPath(checkbookFile, contents: nil, attributes: nil)
}

NSKeyedArchiver.archiveRootObject(checkEntryArrayOfDictionaries,
    toFile: checkbookFile)

//The dictionary to recover to PLAYGROUND
var myCheckBookEntry2:Dictionary = [String  :CheckBookEntry ]()

//A SINGLE INSTANCE OF THE STRUCT TO SAVE EACH TO.
var anIndividualCheckBookEntry = CheckBookEntry()


    let path2 = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    let myStringDictionaryArray:String =  path2[0] as String

   let arrayDictionaryFilePath:String = myStringDictionaryArray.stringByAppendingString("/aCheckbook")
    print(arrayDictionaryFilePath)


if NSFileManager.defaultManager().fileExistsAtPath(arrayDictionaryFilePath) {
    let dictionaryFileArray =
    NSKeyedUnarchiver.unarchiveObjectWithFile(arrayDictionaryFilePath)
        as! [Dictionary <String,AnyObject> ]

    var x = dictionaryFileArray[0]
    var y = dictionaryFileArray[1]
    var z = dictionaryFileArray[2]

    print("\(x) \(y) \(z)")

    var myDictionaryX = x as! [String : AnyObject]
    var myDictionaryY = y as! [String : AnyObject]
    var myDictionaryZ = z as! [String : AnyObject]
}


print("//---------------------------------//")

答案 3 :(得分:1)

这会将包含自制结构的字典保存到NSUserDefaults。但是如果你想保存的不仅仅是一些小数据,你应该使用我在这里发布的文件示例。

import Cocoa


//The key to the dictionary is in the struct here as permanentTimeDateCode

struct CheckBookEntry{

    var permanentTimeDateCode = String()  //value here is also the key for the dictorary it must be a string
    var amountOfTransaction = Double()
    var category = String()
    var payee = String()
    var memo = String()
    var checkNumber = String()

}

var checkBookEntryOne = CheckBookEntry(permanentTimeDateCode: "2015-02--06", amountOfTransaction: 20.00, category: "Properietor", payee: "Balance Forward", memo: "No memo", checkNumber: "00000")

var checkBookEntryTwo = CheckBookEntry(permanentTimeDateCode: "2015-02--05", amountOfTransaction: -15.00, category: "Reference", payee: "Bookstore", memo: "No memo", checkNumber: "00001")

//A dictionary with the date as the key and a CheckBookEntry struct as the value.
var myCheckBookEntry:Dictionary = [String  :CheckBookEntry ]()

myCheckBookEntry["2015-02--06"] = checkBookEntryOne
myCheckBookEntry["2015-02--07"] = checkBookEntryTwo
print(myCheckBookEntry)


//To save these set up an array of dictionaries
var checkEntryArrayOfDictionaries:[[String:AnyObject]] = []

//your struct is no an object that can be saved so it needs to be converted.
//use the variable names from our struct CheckBookEntry as the keys

checkEntryArrayOfDictionaries.append( ["permanentTimeDateCode" : checkBookEntryOne.permanentTimeDateCode,  "amountOfTransaction" : checkBookEntryOne.amountOfTransaction, "catergory" : checkBookEntryOne.category, "payee" : checkBookEntryOne.payee, "memo" :  checkBookEntryOne.memo, "checkNumber": checkBookEntryOne.checkNumber])

checkEntryArrayOfDictionaries.append( ["permanentTimeDateCode" : checkBookEntryTwo.permanentTimeDateCode,  "amountOfTransaction" : checkBookEntryTwo.amountOfTransaction, "catergory" : checkBookEntryTwo.category, "payee" : checkBookEntryTwo.payee, "memo" :  checkBookEntryTwo.memo, "checkNumber": checkBookEntryTwo.checkNumber])

print("//______________printing checkEntryArrayOfDictionaries----//")
print(checkEntryArrayOfDictionaries)

//Save The values
NSUserDefaults().setObject(checkEntryArrayOfDictionaries, forKey: "aCheckbook")

//recovering the struct

//The dictionary to recover to PLAYGROUND
var myCheckBookEntry2:Dictionary = [String  :CheckBookEntry ]()

//A SINGLE INSTANCE OF THE STRUCT TO SAVE EACH TO.
var anIndividualCheckBookEntry = CheckBookEntry()

//RECOVER THE SAVED ENTRY
if let checkEntry2 = NSUserDefaults().arrayForKey("aCheckbook") as? [[String:AnyObject]] {


    for key in checkEntry2{

        anIndividualCheckBookEntry.permanentTimeDateCode = key["permanentTimeDateCode"]! as! String
        anIndividualCheckBookEntry.amountOfTransaction = key["amountOfTransaction"]! as! Double
        anIndividualCheckBookEntry.category =  key["catergory"]! as! String
        anIndividualCheckBookEntry.payee =  key["payee"]! as! String
        anIndividualCheckBookEntry.memo =  key["memo"]! as! String
        anIndividualCheckBookEntry.checkNumber = key["checkNumber"]! as! String

        //LOAD THIS SINGLE ENTRY INTO OUR NEW DICTIONARY
        myCheckBookEntry2[ anIndividualCheckBookEntry.permanentTimeDateCode] = anIndividualCheckBookEntry
    }


    print("//---------------------------------//")
    print(myCheckBookEntry2)

}