1

I need to be able to add and remove an arbitrary number of points to an array. In C++ I could do this easily using vector which allows me to add and remove items of any type.

I know I could store structs in an NSMutableArray using the NSValue class, but I would prefer a faster method than creating and destroy NSValue objects constantly. Is there something similar to the vector class in Objective-C or is there another way to add and remove my structs to arrays (I would prefer not to use Objective C++)? Or am I stuck with NSMutableArray and NSValue.

EDIT: NSMutableData seems like a possible solution.

4 Answers 4

5

The NSArray/NSValue is the traditional way you would store things like CGPoints in an NSArray. How do you know it will be too slow unless you measure it?

Sign up to request clarification or add additional context in comments.

3 Comments

Its also a pain to constantly convert between NSValue and CGPoint for every little thing.
Then create your own point class and store it directly into an NSArray?
Or, even better, add a category to NSValue with something like -(CGPoint)JM_CGPointValue and maybe an -(id)JM_initWithCGPoint:(CGPoint)p (I can't remember off-hand if categories let you add class methods. If so, +(NSValue)JM_valueWithCGPoint:(CGPoint)p could also server you well). That should make it a bit less of a pain to convert between NSValue and CGPoint.
2

If you were not targetting iOS, I would suggest NSPointerArray, which obviates the necessity of wrapping your raw struct datatypes in NSValue containers. However, this class is (unfortunately) not available on iOS.

Apple acknowledge this in their NSArray documentation for iOS, under the title Alternatives to Subclassing.

Before making a custom class of NSArray, investigate NSPointerArray and the corresponding Core Foundation type, CFArray Reference. Because NSArray and CFArray are “toll-free bridged,” you can substitute a CFArray object for a NSArray object in your code (with appropriate casting). Although they are corresponding types, CFArray and NSArray do not have identical interfaces or implementations, and you can sometimes do things with CFArray that you cannot easily do with NSArray. For example, CFArray provides a set of callbacks, some of which are for implementing custom retain-release behavior. If you specify NULL implementations for these callbacks, you can easily get a non-retaining array.

In other words, you can indirectly create an NSArray (or mutable counterpart) that directly holds your non-object datatypes.

2 Comments

Looks like it has the same problems, so I would still have to put it into an NSValue or something.
I rewrote my answer as I now realise that your aversion is to wrapping your datatypes in NSValue containers, not the NSArray itself.
1

You could always make your own vector-esque class in straight up C. The following is an example of a simple stack (probably more appropriately called a PointStack) I hacked together as a proof of concept. Making LinkedLists and the like would not be too difficult either.

EDIT: I see other solutions that are probably better as they don't force you to reinvent the wheel.

struct PointVector {
 CGPoint *data;
 int numItems;
 int maxSize;
};

void resize(struct PointVector *v, int newSize);
void pushPoint(struct PointVector *v, CGPoint newPoint);
void popPoint(struct PointVector *v);

void init(struct PointVector *v) {
 v->data = NULL;
 v->numItems = 0;
 v->maxSize = 0;
}

void pushPoint(struct PointVector *v, CGPoint newPoint) {
 if (v->numItems + 1 > v->maxSize)
  resize(v, (v->maxSize ? v->maxSize * 2 : 1));

 v->data[v->numItems++] = newPoint;
}

void popPoint(struct PointVector *v) {
 if (v->numItems)
  v->numItems--;

}

void resize(struct PointVector *v, int newSize) {
 CGPoint *newData = calloc(sizeof(CGPoint), newSize);

 for (int i = 0; i < v->numItems; i++)
  newData[i] = v->data[i];

 if (v->data != NULL)
  free(v->data);

 v->data = newData;
 v->maxSize = newSize;
}

Comments

0

If this is an option, you can mix the use of C++ and objective-c, write you core algorithm in C++ and then rename your .m files to .mm where you will include and use your c++ code.

2 Comments

I specifically said I was avoiding that.
TomSwift: Yes he did. “I would prefer not to use Objective-C++”.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.