views:

341

answers:

2

I would like to iterate through a CFDictionary (CFPropertyList) and get all values on a specific level.

This would be my dictionary / property-list:


 root
 
  A
  
   foo
   0
   bar
   0
  
  B
  
   foo
   10
   bar
   100
  
  C
  
   foo
   20
   bar
   500
  
 

Using ObjC it would look something like this:

//dict is loaded with the dictionary below "root"
NSDictionary *dict = [...];
NSEnumerator *enumerator = [dict keyEnumerator];
NSString *key;
while (key = [enumerator nextObject]) 
{
    NSLog(key);
};

And it would print out a list of keys to the console like this:

A
B
C

How do you achieve this when using C/C++ on the CoreFoundation-level?

+1  A: 

Based on code from SeeMyFriends:

CFDictionaryRef dict = CFDictionaryCreate(...)
size size = CFDictionaryGetCount(dict);
CFTypeRef *keysTypeRef = (CFTypeRef *) malloc( size * sizeof(CFTypeRef) );
CFDictionaryGetKeysAndValues(dict, (const void **) keysTypeRef, NULL);
const void **keys = (const void **) keysTypeRef;

You can now walk through the pointers in keys[]. Don't forget to free(keys) when you're done.

Remember that dictionary keys are not strings. They're void* (which is why they took the trouble of casting keysTypeRef into keys). Also note that I've only grabbed keys here, but you could also get values at the same time. See the SeeMyFriends code for a more detailed example.

Rob Napier
Thanks a bunch - that did the job.
Till
+4  A: 

Use CFDictionaryApplyFunction to iterate through a dictionary.

static void printKeys (const void* key, const void* value, void* context) {
  CFShow(key);
}
...
CFDictionaryApplyFunction(dict, printKeys, NULL);
KennyTM
Very elegant - thanks!
Till
Agreed. An excellent approach for a wide variety of problems.
Rob Napier