我花了一些认真的时间来调试此问题,但我感到很沮丧。
我试图将自定义对象紧密打包到一起,NSData
以节省将它们保存到磁盘时的空间。我已经为这些自定义对象实现了自定义编码和解码方法。当我打包和解压缩对象时,所有东西都会根据调试器正确初始化。代码运行后立即具有EXC_BAD_ACCESS code=1
或code=2
。
这是编码和解码:
-(instancetype) initWithData:(NSData *)data {
self = [super init];
if (self) {
_memConstants = [[DWMemoryConstants alloc]init];
int arraySize = _memConstants.chunkSize * _memConstants.chunkSize;
NSData* unencodedBlocks[arraySize];
[data getBytes:unencodedBlocks];
_blocks = [[NSMutableDictionary alloc]init];
for (int i = 0; i < 10; i++) {
DWBlock *block = [[DWBlock alloc]initWithData:unencodedBlocks[i]];
[_blocks setObject:block forKey:[NSValue valueWithCGPoint:CGPointFromString(block.blockName)]];
if (i == 0) {
_position = CGPointFromString(block.chunkName);
}
}
_chunkName = NSStringFromCGPoint(_position);
_bounds = CGRectMake(_position.x * _memConstants.chunkSize * kBlockSpriteWidth,
_position.y * _memConstants.chunkSize * kBlockSpriteWidth,
_memConstants.chunkSize * kBlockSpriteWidth,
_memConstants.chunkSize * kBlockSpriteWidth);
}
return self;
}
-(NSData *) customEncode {
NSMutableData *data = [[NSMutableData alloc]init];
NSData* blocks[_blocks.allValues.count];
int count = 0;
for (DWBlock *block in _blocks.allValues) {
blocks[count] = [block customEncode];
count++;
}
[data appendBytes:&blocks length:sizeof(blocks)];
return data;
}
异常发生在此代码的末尾。它成功地首先打印了所有日志消息,并且我已经确认Chunk对象没有任何问题:
-(void) testEncodeDecode {
DWChunk *testChunk = [[DWChunk alloc]initWithPosition:CGPointMake(100, 100)];
NSData *testData = [testChunk customEncode];
NSLog(@"datasize= %@", testData);
DWChunk *unencodedChunk = [[DWChunk alloc]initWithData:testData];
NSLog(@"blocks=%@", unencodedChunk.blocks.allValues);
NSLog(@"this message will print");
}
就像我说的那样,Chunk和Block对象的所有变量都已正确初始化。我怀疑该问题与对象的不当释放有关,但我不知道从这里去哪里。
编辑:我已启用检查僵尸,现在我收到此错误消息:
2014-10-24 11:38:31.775 DigWorld[10622:60b] *** -[NSConcreteMutableData release]: message sent to deallocated instance 0x81790710
编辑:我最初的想法在技术上是不正确的(读代码太快了……),但是实际的错误却是完全相同的。通过保存blocks
,您仅保存指针数组,而不保存实际数据。您可以确保做到这一点:在评论中您说了sizeof(blocks)=3600
和_blocks.allValues.count=900
,因此您只保存了900个指针(* 4字节/指针= 3600字节)
[block customEncode]
然后由ARC处理由创建的实际数据。
之后读取此数组时,您将获得指向NSData
已标记为已释放的内存(以前称为)的指针,从而导致崩溃,并说明启用僵尸程序时的错误消息。
棘手的部分:由于这是程序的同一实例,并且编码和解码彼此相邻运行,因此实际内存尚未被重新分配/覆盖。因此,您得到的印象是对象已正确保存。但是请放心,此内存最终将被其他内容覆盖。您可以通过将其保存NSData
在磁盘上并在程序重新运行时对其进行解码来确保这一点。
在我看来,您正在尝试重新发明轮子。NSCoding
正是为此目的而创建的协议:在磁盘上保留对象图。该NSKeyedArchiver
课程将让你序列化到磁盘中的灵活性和平台的独立性,在良好的测试和记录界面。
您应该利用该架构。即使您决定NSKeyedArchiver
创建的归档文件对于您的目的而言“太大”,也请使用适当的体系结构并创建自己的归档程序。
如果您选择这样做,则可以从此开源NSCoder
子类实现中获得启发(免责声明:我已经写过)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句