Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save and Load Custom Dictionary - NSUserDefaults

I have an [Int:Bool] dictionary and I am trying to save it into my NSDictionary.. However, it crashes with error Attempt to set a non-property-list object

let dictionary = [Int:Bool]()


self.dictionary[2] = true
self.dictionary[3] = false

NSUserDefaults.standardUserDefaults().setObject(dictionary, forKey: "dictionary")

Also, for loading, first I tried this but error logged it strictly requires AnyObject?.

NSUserDefaults.standardUserDefaults().objectForKey("dictionary")

Then I tried this and it logged:

NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool]

I also tried dictionaryForKey. I got..

NSUserDefaults.standardUserDefaults().dictionaryForKey("dictionary")

Cannot assign value to type [String: AnyObject] to type [Int:Bool]


So which one of these 2 is a better approach to take? (The values would be optional in my case I think)

1.
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool] ?? [Int:Bool]()

2.
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool])!
like image 446
senty Avatar asked Dec 05 '22 18:12

senty


1 Answers

Swift 4

Among basic types, UserDefaults can save any object that conforms to Codable protocol. Dictionary is one of the types that implements this protocol. You don't even need to write any custom code:

let dictionary = ["name": "Adam"]

// Save to User Defaults
UserDefaults.standard.set(dictionary, forKey: "names") 

// Read from User Defaults     
let saved = UserDefaults.standard.value(forKey: "names") as? [String: String]

See more info about Codable

Swift 3

You can use UserDefaults to save a Dictionary as long as key and value types are types that can be represented in a plist format (NSNumber, Data, etc.). If that's not the case, we can always serialise other types to Data when writing and deserialise from Data when reading. It can be accomplished with pretty simple extension of UserDefaults using NSKeyArchiver:

extension UserDefaults {
    /// Save dictionary on key
    open func set<Key, Value>(dictionary: [Key: Value]?, forKey key: String) {
        let data = NSKeyedArchiver.archivedData(withRootObject: dictionary as Any)
        set(data, forKey: key)
    }

    // Retrieve dictionary for key
    open func dictionary<Key, Value>(forKey key: String) -> [Key: Value]? {
        guard let data = object(forKey: key) as? Data else { return nil }
        return NSKeyedUnarchiver.unarchiveObject(with: data) as? [Key: Value]
    }
}

Now you can call these methods:

let ages = ["Adam": 25]

// Save
UserDefaults.standard.set(dictionary: ages, forKey: "ages")

// Read
let saved: [String: Int]? = UserDefaults.standard.dictionary(forKey: "ages")
print(saved) // Optional(["Adam": 25])

Swift 2

Save custom data

func setCustomDictionary(dict: [Int: Bool]) {
    let keyedArch = NSKeyedArchiver.archivedDataWithRootObject(dict)

    NSUserDefaults.standardUserDefaults().setObject(keyedArch, forKey: "dictionary")
}

Retrieve data

func getDictionary() -> [Int: Bool]? {
    let data = NSUserDefaults.standardUserDefaults().objectForKey("dict")
    let object = NSKeyedUnarchiver.unarchiveObjectWithData(data as! NSData)
    return object as? [Int: Bool]
}

Usage

var customDictionary = [Int: Bool]()
customDictionary[2] = true
customDictionary[3] = false

// Store data in NSUserDefaults
setCustomDictionary(customDictionary)

// Get data from NSUserDefaults
let userDefaultsDictionary = getDictionary()
like image 102
Said Sikira Avatar answered Dec 28 '22 03:12

Said Sikira