views:

463

answers:

2

Hi I am trying to create a re-sizable array of CGPoints in objective-c. I've have looked into using NSMutableArray however it doesnt seem to allow resizing. Is there something else I can use?

thank you

+2  A: 

NSMutableArray is for objects. For plain old datatypes, use NSMutableData and good old pointer typecasts. It's a resizable unstructured memory buffer, just what you need for a vector of PODs. As for static type safety, Objective C does not give you any of that anyway.

EDIT:

Creating a mutable data object with an initial size n CGPoint structs:

NSMutableData *Data = [NSMutableData dataWithLength: n*sizeof(CGPoint)];

Placing a CGPoint pt into the buffer at the i-th position:

CGPoint pt;
NSRange r = {i*sizeof(CGPoint), sizeof(CGPoint)};
[Data replaceBytesInRange: r withBytes:&pt];

Retrieving a CGPoint from the i-th position into pt:

CGPoint pt;
NSRange r = {i*sizeof(CGPoint), sizeof(CGPoint)};
[Data getBytes: &pt range:r];

Growing the array by n objects:

[Data increaseLengthBy:n*sizeof(CGPoint)];

Hope that covers it. See the NSMutableData reference, and keep in mind that all NSData methods apply to it.

Seva Alekseyev
Hi, Isn't CGPoint an object?
jesse.rj
It's not an object in Objective C sense. It's a struct with two integers in it. CGPoint, CGSize, CGRect - all structures. Unlike C++, in ObjC structs are quite different from classes.
Seva Alekseyev
thanks! Would you happen to have a link for an example of how to use NSMutabledata?
jesse.rj
+1 thanks for your answer! Im going to try the nsmutablearray first cause it seems easier, if I dont get it working ill use NSMutableData
jesse.rj
+8  A: 

Use an NSMutableArray, but just box your CGPoint structs in NSValue objects. Example:

CGPoint myPoint = {0,0};
CGPoint anotherPoint = {42, 69};

NSMutableArray * array = [NSMutableArray array];
[array addObject:[NSValue valueWithCGPoint:myPoint]];
[array addObject:[NSValue valueWithCGPoint:anotherPoint]];

CGPoint retrievedPoint = [[array objectAtIndex:0] CGPointValue];

Note that the +valueWithCGPoint: and CGPointValue methods are only available on the iPhone. However if you need this for the Mac, there are similar methods for dealing with NSPoints, and it's trivial to convert a CGPoint to an NSPoint (you can cast or use NSPointFromCGPoint()).

Dave DeLong
Hidont you have to allocate a size for the array?also does addObject resize the array if necessary?
jesse.rj
@jesse.rj - `NSMutableArray` automatically resizes itself.
Dave DeLong
thanks so much!
jesse.rj
@jesse.rj: In fact, the capacity you specify when you create an NSMutableArray is essentially just a hint that it can use to decide on the best internal behavior. It will still start out with 0 objects and resize to hold as many as you put in.
Chuck
hi, one more question, after I have added a few points to the array how do I check for the size of the array?
jesse.rj
@jesse.rj `NSUInteger count = [array count];`
Dave DeLong
Didn't know about NSValue, +1. Nice to know, but boxing == bad. Fragmented memory, etc.
Seva Alekseyev
@Seva not necessarily. `NSArray`s are insanely useful, and this is the only practical way to store non-objects in them, so I wouldn't say it's exclusively bad. It's definitely not the most ideal solution, but it's far superior to others. ;)
Dave DeLong
NSArrays are insanely useful, yes, but for arrays of objects, not for PODs. Would you use an NSArray for an array of 100000 bytes? With allocation and copy construction overhead for each and every one of them?
Seva Alekseyev
@Seva: For bytes, I would use NSData, since its entire purpose is to be a stream of bytes. But for something other than raw bytes (such as CGPoint), I would usually rather take a small performance penalty than have to treat it as raw bytes and work with pointers constantly. Nobody ever said that writing maintainable code was the root of all evil, you know.
Chuck
Actually, for an array of structs, NSData is worse than a C array and calloc, because you have to manually calculate the offset of each element in the array rather than just being able to write `array[5]`.
Chuck
How much deoptimization for the sake of maintainability is too much? This is a mobile platform, not desktop, so assuming infinite memory (AKA pagefile) might not be a good idea.
Seva Alekseyev