Cocoa and Core Foundation have a wide range of collection classes for managing objects. On the Cocoa side there’s NSArray
, NSDictionary
, NSSet
, NSCountedSet
. These classes are based on the opaque Core Foundation structures CFArray
, CFDictionary
and CFSet
, CFBag
, CFBinaryHeap
and CFTree
. The Cocoa classes are fine 90% of the time, but if you need a more flexibility then Core Foundation can accommodate.
All of the afore mentioned classes are designed to work with objects. Cocoa supplies NSHashTable
and NSPointerArray
for working with pointers and NSIndexSet
for working integers. There are no collection classes for other C primitives or structs. This presents a problem when you want to store an array of non-objects such as floats or ints.
One solution is to wrap the primitive values in an NSValue
(or one of its subclasses) and insert that into an NSArray
. This isn’t a very elegant solution (it involves lots of boiler plate code to get the values in and out of the array) and it consumes a great deal of memory. Another solution is use C++ vectors. I can’t comment on this solution as my C++ knowledge is close to non-existent. A third solution is to use a C array. C arrays are cheap with regards to memory, but the code a bit messier.
To solve this problem in an Objective-C friendly manner I’ve create EMKTypedArray
and EMKMutableTypedArray
. The basic approach is the C solution outlined above. Here’s a usage example:
//Create an array
CGPoint points[2] = {CGPointMake(10,10), CGPointMake(20, 20)};
EMKMutableTypedArray *pointArray = [EMKMutableTypedArray typedArrayWithTypeSizeof:sizeof(CGPoint) bytes:points count:2 defaultValue:&CGPointZero];
CGPoint value;
uint i, pointCount;
for (i = 0, pointCount = [pointArray count]; i < pointCount; i++)
{
[pointArray getValue:&value atIndex:i];
NSLog(@"%i: %f, %f", i, value.x, value.y);
}
//0: 10, 10
//1: 20, 20
//add a value
CGPoint point = (CGPoint){.x = 40, .y = 40};
[pointArray setValue:&point atIndex:3];
for (i = 0, pointCount = [pointArray count]; i < pointCount; i++)
{
[pointArray getValue:&value atIndex:i];
NSLog(@"%i: %f, %f", i, value.x, value.y);
}
//0: 10, 10
//1: 20, 20
//2: 0, 0
//3: 40, 40
//shrink the array
[pointArray trimToLength:2];
for (i = 0, pointCount = [pointArray count]; i < pointCount; i++)
{
[pointArray getValue:&value atIndex:i];
NSLog(@"%i: %f, %f", i, value.x, value.y);
}
//0: 10, 10
//1: 20, 20
EMKTypedArray
and EMKMutableTypedArray
are part of my GitHub project, EMKPantry.