01.02.2014 Views

Objective-C Fundamentals

Objective-C Fundamentals

Objective-C Fundamentals

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Dictionaries<br />

87<br />

Because a dictionary is made up of key/value pairs, NSDictionary provides two<br />

convenient messages to obtain enumerators to iterate over each entry in the dictionary.<br />

The keyEnumerator message provides an enumerator that iterates over all keys in<br />

the dictionary, while objectEnumerator performs a similar task but iterates over all<br />

the values instead:<br />

NSEnumerator *enumerator = [myDetails keyEnumerator];<br />

id key;<br />

while (key = [enumerator nextObject]) {<br />

NSLog(@"Entry has key: %@", key);<br />

}<br />

Using the keyEnumerator message, this code snippet lists the name of each key currently<br />

stored in the dictionary. Try using the objectEnumerator message on the first<br />

line, and you’ll see the values listed instead. Fast enumeration is also possible, and if<br />

you use the dictionary object directly, it iterates over all of the keys:<br />

for (id key in myDetails) {<br />

id value = [myDetails objectForKey:key];<br />

}<br />

NSLog(@"Entry with key '%@' has value '%@'", key, value);<br />

This code sample also demonstrates that in the iteration loop it’s possible to use<br />

objectForKey: to obtain the value that matches the current key. When placing code<br />

in an enumeration loop, such as the one just shown, you must be careful that you<br />

don’t mutate the data structure. As an example, you may think that one way to remove<br />

all the entries in a dictionary (other than the more logical removeAllObjects) would<br />

be the following code snippet:<br />

for (id key in dictionary) {<br />

[dictionary removeObjectForKey:key];<br />

}<br />

Although this appears conceptually correct, the code snippet has a fundamental flaw<br />

that will result in an exception similar to the following and crash the application:<br />

*** Terminating app due to uncaught exception 'NSGenericException', reason:<br />

'*** Collection was mutated while being<br />

enumerated.'<br />

If you enumerate over a data structure by using fast enumeration or an NSEnumerator,<br />

your code shouldn’t modify the associated data structure until your enumeration has<br />

completed. Modifying the contents of an array or dictionary that’s currently being<br />

enumerated will alter its internal data structure and cause any associated enumerators<br />

to become invalid. If you need to enumerate through a dictionary and potentially add<br />

or remove entries before enumeration has completed, you should first make a copy of<br />

all the keys by calling a method such as allKeys. This method creates an array and<br />

copies a list of all keys currently in the dictionary into that array. This allows you to

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!