views:

1598

answers:

6

I am finding some difficulty in accessing mutable dictionary keys and values in Objective-C.

Suppose I have this:

NSMutableDictionary *xyz=[[NSMutableDictionary alloc] init];

I can set keys and values. Now, I just want to access each key and value, but I don't know the number of keys set.

In PHP it is very easy, something as follows:

foreach ($xyz as $key => $value)

How is it possible in Objective-C?

+2  A: 

I suggest you to read the Enumeration: Traversing a Collection’s Elements part of the Collections Programming Guide for Cocoa. There is a sample code for your need.

Laurent Etiemble
Those are good links, although the code @zneak posted is much simpler and faster, if you can build for 10.5+ or iPhone.
Quinn Taylor
+10  A: 
for (NSString* key in xyz) {
    id value = [xyz objectForKey:key];
    // do stuff
}

This works for every class that conforms to the NSFastEnumeration protocol (available on 10.5+ and iPhone OS). I suggest you read about fast enumeration in the Introduction to the Objective-C language.

Oh, I should add however that you should NEVER modify a collection while enumerating through it.

zneak
Oh, I should add however that you should __NEVER__ modify a collection while enumerating through it.
zneak
I copied your comment into your answer, since it's a pretty important warning.
benzado
+1 Indeed, your app will throw an exception should you try.
Dave DeLong
A: 

You can use -[NSDictionary allKeys] to access all the keys and loop through it.

gcamp
True, but this does create an extra autoreleased array, which can be quite wasteful, especially for dictionaries with lots of keys.
Quinn Taylor
+2  A: 

Fast enumeration was added in 10.5 and in the iPhone OS, and it's significantly faster, not just syntactic sugar. If you have to target the older runtime (i.e. 10.4 and backwards), you'll have to use the old method of enumerating:

NSDictionary *myDict = ... some keys and values ...
NSEnumerator *keyEnum = [myDict keyEnumerator];
id key;

while ((key = [keyEnum nextObject]))
{
    id value = [myDict objectForKey:key];
    ... do work with "value" ...
}

You don't release the enumerator object, and you can't reset it. If you want to start over, you have to ask for a new enumerator object from the dictionary.

dreamlax
+4  A: 

Just to not leave out the 10.6+ option for enumerating keys and values using blocks...

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];

If you want the actions to happen concurrently:

[dict enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
                              usingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];
Quinn Taylor
3 different ways to enumerate through a dictionary . . . heh, this reminds me of the "Strangest Language Feature" answer where VB has 7 different kinds of loops.
dreamlax
Well... objectEnumerator was added in 1994, the for(... in ...) in about 2006, and Blocks were added in 2009. The block form of enumeration is natural fallout.
bbum
+1  A: 

Here whats the best way to create a incremental variable here, like if you wanted to know this is the nth time the looping is running

i created a variable int, outside the loop, but inside the block is says the variable is read only.

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];

thanks.

Jinah Adam