How to use For Loop through keys of NSUserDefault Dictionary

2.4k views Asked by At

I can't get a value out of this computed property (userList)...is my init set up correctly? I'm trying to build a list that will populate the rows in my table view. (*Edit: I've edited my question with a saveData function, but "cannot invoke setObject" with an argument list of type ([String : User], forKey: String)" –

import Foundation

class DataManager {

    static let sharedInstance = DataManager()

    var users = [String : User]()


    init() {
        let userDefaults = NSUserDefaults.standardUserDefaults()

        if let var userFromDefaults = userDefaults.objectForKey("userKey") as? [String : User] {

            users = userFromDefaults

        }

        else {
            // add default values later

        }


    }

   func saveData() {
    let userDefaults = NSUserDefaults.standardUserDefaults()
    userDefaults.setObject(users, forKey: "userKey")
}

    var userList: [String] {
        var list: [String] = []
        for name in users.keys {
            list.append(name)
        }
        list.sort(<)
        return list
    }

My viewcontroller:

import UIKit

class NameViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {


    var users: [String] = DataManager.sharedInstance.userList

User Struct with a method to convert into json:

import Foundation

struct User {
    var name = ""
    var stores: [Store] = []

    init?(json: [String: AnyObject]) {
        if let name = json["name"] as? String,
            storesJSON = json["stores"] as? [[String: AnyObject]]
        {
            self.name = name
            self.stores = storesJSON.map { Store(json: $0)! }
        } else {
            return nil
        }
    }

    init() { }

    func toJSON() -> [String: AnyObject] {
        return [
            "name": name,
            "stores": stores.map { $0.toJSON() }
        ]
    }

}
3

There are 3 answers

1
Duncan C On

As Matt pointed out in his comment, you need to save contents to NSUserDefaults before you can read them.

Something else that will prevent your code from working:

NSUserDefaults will only save "property list" objects (NSString, NSData, NSDate, NSNumber, NSArray, or NSDictionary objects or their Swift equivalents.)

If you try to save anything else, or a collection containing anything but those data types, the save fails and you get nil when you try to read it back. Your code shows you trying to save a dictionary where the value for each key is an object of type "User". That's going to fail since "User" is not one of the short list of "property list" object types.

0
Icaro On

You can grab all keys/Values using (from apple documentation)

dictionaryRepresentation() Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.

Using this you can loop all the elements in the dictionary

for element in NSUserDefaults.standardUserDefaults().dictionaryRepresentation() {
        println(element)
        //Do what you need to do here
}

You can also retrieve just the keys:

println(NSUserDefaults.standardUserDefaults().dictionaryRepresentation().keys.array);

or just the values

println(NSUserDefaults.standardUserDefaults().dictionaryRepresentation().values.array);
1
Patrick Lynch On

This is not a good user of NSUserDefaults, which is meant to store preferences and other small bits of data between app launches. See the documentation on NSUserDefaults.

You should be managing this dictionary of users in memory when you are displaying data, and if you want to persist it to disk between app launches you should use CoreData or make your User class conform to NSCoding and read/write it with archiving. Here's a nice tutorial.