You have more options for creating and copying collection objects than with most other Core Foundation types. Collection objects can be immutable or mutable, and, if the latter, can be either fixed-size or variable-size (immutable objects are, of course, always fixed-size). Each of these variants has its own possibilities and limitations.
Because the values (including, for dictionaries, keys) in an immutable collection cannot change once the collection is created, you must supply these values when you create the object. The acceptable form for these initializing values is a C array (unless the collection is to hold only one value). The input parameters must specify the address of this C array. Listing 1 illustrates how a CFArray object might be created.
Listing 1 Creating an immutable CFArray object
CFStringRef strs[3]; CFArrayRef anArray; strs[0] = CFSTR("String One"); strs[1] = CFSTR("String Two"); strs[2] = CFSTR("String Three"); anArray = CFArrayCreate(NULL, (void *)strs, 3, &kCFTypeArrayCallBacks); CFShow(anArray); CFRelease(anArray);
Notice the final parameter of the
CFArrayCreate
call, the address of the
kCFTypeArrayCallBacks
constant. This constant identifies a predefined
callback structure
for the CFArray type. The functions that create and copy collection objects such as arrays, dictionaries, sets, and bags require you to specify callback structures. These structures contain pointers to callbacks function that control how values (and keys) of a collection are kept, evaluated, and described. Each of the collection types listed above defines one or more predefined callback structures that you can use when the values of the collection are Core Foundation objects.
The
CFDictionaryCreate
function, which creates an immutable dictionary object, is somewhat different from the related Collection Services functions. It requires you to specify not only one or more values but a matching set of keys for these values. The typical means for specifying these lists of values and keys are two C arrays. Listing 2 provides a simple example.
Listing 2 Creating an immutable CFDictionary object
CFStringRef keys[3]; CFStringRef values[3]; CFDictionaryRef aDict; keys[0] = CFSTR("Key1"); keys[1] = CFSTR("Key2"); keys[2] = CFSTR("Key3"); values[0] = CFSTR("Value1"); values[1] = CFSTR("Value2"); values[2] = CFSTR("Value3"); aDict = CFDictionaryCreate(NULL, (void *)keys, (void *)values, 3, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFShow(aDict); CFRelease(aDict);
The keys in one array are positionally matched with the values in the other array. Thus, in the example above, the third element in the
keys
C array is the key for the third element in the
values
array. Note that for creating dictionary objects you must specify initialized callback structures for both the keys and the values.
To create a mutable collection object you call the CreateMutable function appropriate to a given type. This call creates an empty (that is, valueless) collection to which you then add values.
CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(myDictionary, CFSTR("Age"), CFSTR("35"));
A similar interface exists for creating mutable copies, except that these functions do not require you to specify callbacks. The reason for this omission--applicable to both mutable and immutable copies--is that the callbacks used by the original object are used by the copy to retain, release, compare, and describe its values.
/* props is an existing dictionary */ CFMutableArrayRef urls = CFArrayCreateMutableCopy(NULL, 0, (CFArrayRef)CFDictionaryGetValue(props, kCFFileURLDirectoryContents));
In functions that create or copy mutable collection objects the second parameter is an integer that specifies the capacity of the collection, or the maximum number of values that the collection can safely store. A mutable collection with a capacity greater than zero is said to be fixed-size. If this parameter is zero, as in the above example, the call requests a variable-size collection. A variable-size collection can contain any number of values, limited only by address space and available memory.