Re: Help with NSPointerArray and NSMapTable
Jonathan Dann <[email protected]>
| Newsgroups | gmane.comp.macosx.devel |
|---|---|
| Message-ID | <[email protected]> |
Looks like I can't post from my work email...
On 21 Sep 2009, at 20:22, Christiaan Hofman wrote:
> I am trying to create arrays and dictionaries containing non-object
> types like NSInteger, CGFloat, and structs like NSRect. This should
> be possible using NSPointerArray/NSMapTable and appropriate pointer
> functions. But I am very much confused about which pointer function
> options to use and how to add/remove values.
[snip]
Hi Christiaan,
You're along the right lines but you need to also set the sizeFunction
on the NSPointerFunctions. This is a pointer to a function that
returns the size of type you'll be using in the array. The collections
(presumably) use the size function in the malloc() call when they take
ownership of the value. I have some categories on NSPointerFunctions
and NSPointerArray for the common struct types:
@implementation NSPointerFunctions (ESAdditions)
static NSUInteger _ESPointerArrayCGRectStructSize(const void *item)
{
return sizeof(CGRect);
}
static NSUInteger _ESPointerArrayCGPointStructSize(const void *item)
{
return sizeof(CGPoint);
}
static NSUInteger _ESPointerArrayNSRangeStructSize(const void *item)
{
return sizeof(NSRange);
}
static NSUInteger _ESPointerArrayCGSizeStructSize(const void *item)
{
return sizeof(CGSize);
}
+ (NSPointerFunctions *)pointerFunctionsForNSRange;
{
NSPointerFunctions *aPointerFunctions = [NSPointerFunctions
pointerFunctionsWithOptions:(NSPointerFunctionsStructPersonality|
NSPointerFunctionsMallocMemory|NSPointerFunctionsCopyIn)];
[aPointerFunctions setSizeFunction:&_ESPointerArrayNSRangeStructSize];
return aPointerFunctions;
}
+ (NSPointerFunctions *)pointerFunctionsForCGRect;
{
NSPointerFunctions *aPointerFunctions = [NSPointerFunctions
pointerFunctionsWithOptions:(NSPointerFunctionsStructPersonality|
NSPointerFunctionsMallocMemory|NSPointerFunctionsCopyIn)];
[aPointerFunctions setSizeFunction:&_ESPointerArrayCGRectStructSize];
return aPointerFunctions;
}
+ (NSPointerFunctions *)pointerFunctionsForCGPoint;
{
NSPointerFunctions *aPointerFunctions = [NSPointerFunctions
pointerFunctionsWithOptions:(NSPointerFunctionsStructPersonality|
NSPointerFunctionsMallocMemory|NSPointerFunctionsCopyIn)];
[aPointerFunctions setSizeFunction:&_ESPointerArrayCGPointStructSize];
return aPointerFunctions;
}
+ (NSPointerFunctions *)pointerFunctionsForCGSize;
{
NSPointerFunctions *aPointerFunctions = [NSPointerFunctions
pointerFunctionsWithOptions:(NSPointerFunctionsStructPersonality|
NSPointerFunctionsMallocMemory|NSPointerFunctionsCopyIn)];
[aPointerFunctions setSizeFunction:&_ESPointerArrayCGSizeStructSize];
return aPointerFunctions;
}
@end
@implementation NSPointerArray (ESExtensions)
+ (id)rangePointerArray;
{
return [[[self alloc] initWithPointerFunctions:[NSPointerFunctions
pointerFunctionsForNSRange]] autorelease];
}
+ (id)rectPointerArray;
{
return [[[self alloc] initWithPointerFunctions:[NSPointerFunctions
pointerFunctionsForCGRect]] autorelease];
}
+ (id)pointPointerArray;
{
return [[[self alloc] initWithPointerFunctions:[NSPointerFunctions
pointerFunctionsForCGPoint]] autorelease];
}
+ (id)sizePointerArray;
{
return [[[self alloc] initWithPointerFunctions:[NSPointerFunctions
pointerFunctionsForCGSize]] autorelease];
}
@end
If you add NS_BUILD_32_LIKE_64 to the preprocessor macros in Xcode,
you can use CG/NS Rect, Point and Size interchangeably.
Note that +[NSPointerArray pointerArrayWithPointerFunctions:] seems to
crash on 10.5.x, hence the -initWith... calls.
In you client code, do something like
NSRect aRect = NSZeroRect;
NSPointerArray *aRectArray = [NSPointerArray rectPointerArray];
[aRectArray addPointer:&aRect];
// some time later ......
NSRect aRect = *(NSRectPointer)[aRectArray pointerAtIndex:index]
Hope this helps,
Jonathan