1

I'm trying to learn about dictionaries and nsusersdefaults in swift. I wrote a small program that creates a dictionary of strings and uses that dictionary to populate a tableview. Next I save the dictionary to NSUserDefaults. Everything at this point is working great. It's when I attempt to pull the dictionary back out and use it that things go wrong.

Here is my complete code, the error is on the line myDict = userDefaults and the error is Cannot assign a value of type '[String : AnyObject]' to a value of type '[Dictionary]':

import UIKit


// Create dictionary
var myDict = [Dictionary<String,String>()]


class TableViewController: UITableViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    print(myDict.count)

    // Dictionary starts out with 1 item when new
    // so remove that one thing and create it if needed

    if myDict.count == 1 {

        myDict.removeAtIndex(0)

        // Put some stuff in the dictionary

        myDict.append(["name":"Bill","age":"39","sex":"male"])
        myDict.append(["name":"Nick","age":"8","sex":"male"])
        print(myDict)


    } else {

        if let userDefaults = NSUserDefaults.standardUserDefaults().dictionaryForKey("myDict") {

            myDict = userDefaults


        }

    }

}


override func viewDidAppear(animated: Bool) {
    NSUserDefaults.standardUserDefaults().setObject(myDict, forKey: "myDict")
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}



// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return myDict.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

    // Configure the cell...

    cell.textLabel!.text = myDict[indexPath.row]["name"]

    return cell
 }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
Bill
  • 123
  • 1
  • 7
  • My code didn't exactly get captured by the {} in the view above but it is all there. – Bill Aug 20 '15 at 20:39

2 Answers2

3
var myDict = [Dictionary<String,String>()]

should be

var myDict = [String:String]()

at least in swift 2.0

For your problem it should actually be

var myDict = [String:AnyObject]()

because that is what you get from NSUserdefaults. When you access a value from a key in the dictionary you need to cast it to String.

der_michael
  • 3,151
  • 1
  • 24
  • 43
  • Thanks! I saw this solution when I was searching and I tried it but it breaks all the rest of my code. I can no longer append or remove. I guess I have to append and remove differently then I am above? – Bill Aug 20 '15 at 20:50
  • in your code you have a list of dictionaries actually. Is that what you want? I think you want a single dictionary, no? A list of Dictionaries would be `var myDict = [[String:String]]()` – der_michael Aug 20 '15 at 20:52
  • I wanted a single dictionary that I can add groups of "names,ages,sex" to, or anything really and use it to populate a tableview with after storing and retreaving from nsuserdefaults. After changing my code to var myDict = [String:String]() all of my myDict.appends are broken. Sorry if I'm missing something simple, I'm still learning. – Bill Aug 20 '15 at 20:57
  • Now I get AnyObject doesn't have an append. – Bill Aug 20 '15 at 21:01
  • Ok, so easiest would be to convert your *group dictionary* to a class with properties and stuff them in an array. In your case, you would need to go with `var myDict = [[String:String]]()` then and `NSUserDefaults.standardUserDefaults().dictionaryForKey("myDict")` would actually become `NSUserDefaults.standardUserDefaults().arrayForKey("myDict")` – der_michael Aug 20 '15 at 21:02
  • Please understand that you are placing an array if dictionaries inside a dictionary. That is what I think where your biggest confusion comes from. – der_michael Aug 20 '15 at 21:03
  • myDict = userDefaults is back to complaining I cant assign anyobject to string – Bill Aug 20 '15 at 21:10
  • yes, that goes back to my initial answer. If you want to make that direct assignment you need to declare `var myDict = [[String:AnyObject]]()` – der_michael Aug 20 '15 at 21:46
-2

Instead of setObject use the sync method:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];        
    if (![defaults objectForKey:@"vesselType_preference"])
    {
        [defaults setObject:@"Dry" forKey:@"vesselType_preference"];
    }
    [[NSUserDefaults standardUserDefaults] synchronize];
Community
  • 1
  • 1
Dmitry Sadakov
  • 2,128
  • 3
  • 19
  • 34