2010-02-17 7 views
8

Vorrei eseguire un iterazione attraverso un CFDictionary (CFPropertyList) e ottenere tutti i valori su un livello specifico.Come enumerare le chiavi CFProperyList/CFDictionary

Questo sarebbe il mio dizionario/proprietà-list:


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

Utilizzando objC sarebbe simile a questa:

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

E sarebbe stampare un elenco di chiavi per la console come questo:

 
A 
B 
C 

Come si fa a raggiungere questo quando si utilizza C/C++ a livello di CoreFoundation?

risposta

10

Basato sul codice da 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; 

È ora possibile camminare attraverso i puntatori in keys[]. Non dimenticare di free(keys) quando hai finito.

Ricordare che le chiavi del dizionario non sono stringhe. Sono void* (motivo per cui si sono presi la briga di lanciare keysTypeRef in keys). Nota anche che ho solo preso le chiavi qui, ma potresti anche ottenere valori allo stesso tempo. Vedi il codice SeeMyFriends per un esempio più dettagliato.

+0

grazie un gruppo - che ha fatto il lavoro. – Till

+0

Il metodo CFDictionaryGetKeysAndValues ​​utilizza un puntatore a un puntatore a un array di chiavi. Perché, allora, non si passa l'indirizzo del puntatore "keysTypeRef" (che sarebbe un puntatore a quel puntatore)? – erikprice

+0

'CFDictionaryGetKeysAndValues' prende un puntatore a un array di puntatori (' void ** '), non un puntatore a un puntatore a un array di puntatori (' void *** '). Ricorda, 'CFTypeRef' stesso è un puntatore. –

41

Utilizzare CFDictionaryApplyFunction per scorrere un dizionario.

static void printKeys (const void* key, const void* value, void* context) { 
    CFShow(key); 
} 
... 
CFDictionaryApplyFunction(dict, printKeys, NULL); 
+0

Molto elegante - grazie! – Till

+1

concordato. Un approccio eccellente per un'ampia varietà di problemi. –

4

CFCopyDescription è utile durante il debug ...

CFCopyDescription 
Returns a textual description of a Core Foundation object. 

    CFStringRef CFCopyDescription (
     CFTypeRef cf 
    );