« The Storage Series, Part Three

Posted by Andy Monitzer on March 17, 2001 [Feedback (0) & TrackBack (1)]

// Part Three: Dictionaries

Let's suppose you go to a restaurant (I know, nerds only eat pizza at home, but let's pretend you get out sometime). When you get a menu, you usually have something like the following list:

Cherry Coke  $2
Pizza  $10
Meat Balls  $8
Wiener Schnitzel  $10

The Common Nerd (me and you) suddenly thinks "how would I save this list in Cocoa?"

Well, the first thing one would come into mind after reading part one and two of this series (which you should do if you haven't done so already) would be an array. More experienced coders would even think about an array of arrays (commonly known as two-dimensional arrays) in this way:

  | -> "Cherry Coke" -> 2
  | -> "Pizza" -> 10
  | -> "Meat Balls" -> 8
  | -> "Wiener Schnitzel" -> 10

So, there's the main list of all meals. Each item of the meal is a list in itself, which consists of the name of the meal at position 0 and the price at position 1. This should be nothing new for you.

This is possible, but I think it's bad behavior because you have different kinds of objects (strings and numbers) in one list, which could lead to a lot of trouble later on. Furthermore, You end up creating get five NSArrays, which means you've also created a lot of memory overhead. Wouldn't it be much better if we had one list of these?


// Now Show Me the Thing

That's what dictionaries (class NSDictionary) are for. They "translate" things into other things. For example, one pizza would be translated to $10. Dictionaries use two different kinds of objects: keys and values. A key would be the left side of the equation ("Pizza") - it has to be unique (there is only one "Cherry Coke"), and the value would be the right side - it doesn't need to be unique (two items can cost $10). Like in NSArrays, all objects have to be childs of NSObject.

The above example would then translate to...

key = "Cherry Coke", value = 2
key = "Pizza", value = 10
key = "Meat Balls", value = 8
key = "Wiener Schnitzel", value = 10

...or programmatically...

- (NSDictionary*)getMeTheMenu
  NSMutableDictionary *menu = [NSMutableDictionary dictionary];
  [menu setObject:[NSNumber numberWithInt:2] forKey:@"Cherry Coke"];
  [menu setObject:[NSNumber numberWithInt:10] forKey:@"Pizza"];
  [menu setObject:[NSNumber numberWithInt:8] forKey:@"Meat Balls"];
  [menu setObject:[NSNumber numberWithInt:10] forKey:@"Wiener Schnitzel"];

  return menu;

[NSNumber numberWithInt:] is necessary to get an object that is a child of NSObject. And I use an NSMutableDictionary instead of an NSDictionary, because I modified it after the creation. I could also use:

- (NSDictionary*)getMeTheMenu
  NSDictionary *menu = [NSDictionary dictionaryWithObjectsAndKeys:
    @"Cherry Coke",      [NSNumber numberWithInt:2],
    @"Pizza",            [NSNumber numberWithInt:10],
    @"Meat Balls",       [NSNumber numberWithInt:8],
    @"Wiener Schnitzel", [NSNumber numberWithInt:10], nil];
  return menu;

(There are some more ways to do it, but I won't discuss this further because it's getting boring and it's very similar.)


// Getting the Best Out of Dictionaries

So, you want how much a pizza is? No problem, just call

int price = [[menu objectForKey:@"Pizza"] intValue];

intValue is used to get the integer out of the NSNumber.

Or maybe you wanted a list of meals available here?

NSArray *list = [menu allKeys];

And for the record, here are all prices you could pay (not particularly useful in this example):

NSArray *list = [menu allValues];


// Random Thoughts About Dictionaries

  • When using dictionaries in your applications, you have to design it more carefully. Arrays are easy to implement, they're just a list of items, nothing exiting. On the other side, dictionaries can be used in many ways (for example, the above example could also be implemented by using an array of 2-key dictionaries which implement something like key = "name", value = "Pizza" / key = "price", value = 10 and so on...). In general, the more objects you use, the more memory overhead and the more speed loss you will get.
  • Dictionaries are particularly useful for implementing tables (in a list of dictionaries that look like tableheader = item, tableheader = item,...), since the table headers can be moved around, changing the order, making arrays useless.
  • The key is usually an NSString, but the only requirement that it has is that it has to respond to - isEqualTo:(id)anObject;.
  • Another common approach is to use a custom object for the value.

In general, there is no "right" and "wrong" way of doing it.

Post a comment