簡體   English   中英

儲存字典 <String, CustomObject> 在Swift中的NSUserDefaults中

[英]Store a Dictionary<String, CustomObject> in NSUserDefaults in Swift

我有一個創建的Dictionary ,其中的鍵是一個String ,值是一個稱為SectorCoordinate.的自定義對象SectorCoordinate.
我只想將整個織補內容存儲在NSUserDefaults ,但是當我這樣做時,Xcode說:

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

我真的很困惑 我以為AnyObject是Objective-C id Swift版本,應該能夠容納任何對象。

我已經看到並嘗試實現了針對[String: String]字典(例如JSON操作)的一系列解決方案,但是這些解決方案均無效,並且出現類似的錯誤。 我什至試圖破壞鍵值對,並且在嘗試甚至將一個SectorCoordinate (它本身只是一個帶有一堆StringInt和日期的struct存儲為一個時,也遇到了相同的錯誤。 AnyObject

有人對如何將半復雜對象和/或其字典存儲為AnyObject有任何建議嗎? 看來這應該簡單得多。

Apple文檔說明了有關NSUserdefaults setObject:forKey:方法的信息:

value參數只能是屬性列表對象:NSData,NSString,NSNumber,NSDate,NSArray或NSDictionary。 對於NSArray和NSDictionary對象,它們的內容必須是屬性列表對象。 請參見《屬性列表編程指南》中的“什么是屬性列表?”。

因此,例如,您可以將Swift字典[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。

您可以將任何對象存儲在NSUserDefs中,請參閱NSUserDefaults Apple文檔:

NSUserDefaults類提供了用於訪問常見類型(例如浮點數,雙精度數,整數,布爾值和URL)的便捷方法。 默認對象必須是屬性列表,即NSData,NSString,NSNumber,NSNumber,NSDate,NSArray或NSDictionary的一個實例(或用於集合的實例的組合)。 如果要存儲任何其他類型的對象,通常應將其歸檔以創建NSData實例。 有關更多詳細信息,請參見“首選項和設置編程指南”。

要擁有可以無縫轉換為NSData的對象,請確保您的類符合NSCoding協議(即,可以對其進行歸檔和取消歸檔)。 Swift有時也會希望您的類也符合NSSecureCoding。

我已經回答了如何在此頁上的其他地方使用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("//---------------------------------//")

這會將包含自制結構的字典保存到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)

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM