一直在解决这个问题。我使用box2D并将b2fixture编码为NSValue。使用
解码时会出现问题[value getValue:&fixture];
这段代码在我的旧Mac上工作得很好,但是在过去的4年中,某些地方似乎发生在矩阵中!
这里是编码和解码的相关代码:
vertGrid = [[NSMutableArray alloc] initWithCapacity:(NSUInteger) xUnits];
for (int x = 0; x <= xUnits; x++) {
b2Fixture *fixture = ... (not relevant)
NSValue *wrappedValue = [NSValue value:&fixture withObjCType:@encode(struct b2Fixture)];
[vertGrid addObject:wrappedValue];
}
//test I can unwrap the vertGrid
for (NSValue *value in vertGrid) {
b2Fixture *fixture;
[value getValue:&fixture];
NSLog(@"yo yo yo");
}
答案 0 :(得分:1)
如果它正在运作,那么纯粹的机会。你不小心复制指针,而不是包装内容。内存管理和内存对齐的变化现在可能会“破坏”它(32位与64位?)。
无论如何,你的包装和解包都是错误的,因为它们都有一个额外的(不正确的)间接。让我们从包装值开始。您的代码是:
b2Fixture *fixture = ... (not relevant)
NSValue *wrappedValue = [NSValue value:&fixture withObjCType:@encode(struct b2Fixture)];
-[NSValue value:withObjCType:]
的文档提供了必要的信息:
value
:指向要存储在新值对象中的数据的指针。
由于您希望存储数据,因此您需要传递struct b2Fixture *
,因为该方法将从该存储位置读取数据,但您传递的是struct b2Fixture **
。因此,将复制错误的数据(指针而不是数据)。
以下是该方法实际工作原理的另一个提示:
此方法与
valueWithBytes:objCType:
具有相同的效果,可能会在将来的版本中弃用。您应该使用valueWithBytes:objCType:
代替。
换句话说:该方法复制内容,而不是指向内容的指针。方法名称没有明确说明使用valueWithBytes:objCType:
是更好的选择的原因。
因此,您对值进行包装的调用必须是:
NSValue *wrappedValue = [NSValue value:fixture withObjCType:@encode(struct b2Fixture)];
(注意缺少的&
)。
接下来,打开。你有:
b2Fixture *fixture;
[value getValue:&fixture];
再次,让我们看看documentation of -[NSValue getValue:]
,它说:
buffer
:要复制值的缓冲区。缓冲区必须足够大以容纳值
这意味着您需要分配存储空间。这里有两个选项:在库存或堆上分配。
// Allocate on the stack:
b2Fixture fixture;
[value getValue:&fixture];
// Allocate on the heap:
b2Fixture *fixture = malloc(sizeof(b2Fixture));
[value getValue:fixture]; // No "&"!
...
free(fixture);
评论后更新:
由于您似乎正在尝试包装C ++对象,因此您需要采用不同的方式。我有两种解决方法:
+[NSValue valueWithPointer:]
和-[NSValue pointerValue]
。这假设对象存在于堆上,并使内存管理更复杂。