11

I'm storing Chipmunk Physics' cpShape objects in an NSMutableDictionary by way of NSValue objects and the following lines of code:

NSValue *shapeValue = [[NSValue alloc] initWithBytes: shape objCType: @encode(cpShape)];
[staticBodiesInUse setObject: shapeValue forKey: name];

I now need to get the cpShape back out, to compare it to another shape. How can I do that? I see a getValue: method in NSValue but it needs a buffer, not too sure what to do with it.

jscs
  • 63,694
  • 13
  • 151
  • 195
Luke
  • 9,512
  • 15
  • 82
  • 146

2 Answers2

15

So the answer by trojanfoe is only partly correct.

There is a huge problem with doing that. When you create the NSValue that way, you are copying the cpShape struct, and getting it back out, you are copying it again. cpShape structs are pretty much exclusively used by reference. Each time you copy it, you get a new reference to the new copy, and some of those copies exist on the stack and get destroyed silently and automatically. Very very bad.

Instead you want to create a NSValue using [NSValue valueWithPointer:shape] and get that pointer back using [value pointerValue]. This way the NSValue is only storing a pointer to the original cpShape.

Stunner
  • 12,025
  • 12
  • 86
  • 145
slembcke
  • 1,359
  • 7
  • 7
  • And using a `cpShape *` is *problem free*? I don't think so and will lead to insidious bugs unless used very carefully. – trojanfoe Feb 20 '14 at 09:07
  • @slembcke can you elaborate a bit more on why creating a copy of the struct in the current stack frame is bad (or worse than passing around pointers to the struct)? Or is that due to the way chipmunk operates? – dev Dec 31 '15 at 09:42
8

Isn't it simply:

NSValue *value = [staticBodiesInUse objectForKey:name];
cpShape shape;
[value getValue:&shape];
trojanfoe
  • 120,358
  • 21
  • 212
  • 242