使用NSKeyedUnarchiver解码时的EXC_BAD_ACCESS

时间:2012-08-10 22:14:08

标签: objective-c macos

我在decodeObjectForKey:call上得到一个EXC_BAD_ACCESS。如果有人能在这里发现一个明显的错误,我将不胜感激:

- (NSData *)serialize:(id <NSCoding>)object {
  NSMutableData *data = [[NSMutableData alloc] init];
  NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
  [archiver setOutputFormat:NSPropertyListBinaryFormat_v1_0];
  [archiver encodeObject:object forKey:@"myobject"];
  [archiver finishEncoding];
  return data;
}

- (id)deserialize:(NSData *)data {
  NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
  unarchiver.delegate = self;
  id object = [unarchiver decodeObjectForKey:@"myobject"];
  [unarchiver finishDecoding];
  return object;
}

NSCoding协议的实现方式如下:

- (id)initWithCoder:(NSCoder *)aDecoder {
  self = [super init];
  if (self != nil) {
    _fields = [aDecoder decodeObjectForKey:@"fields"];
    _entries = [aDecoder decodeObjectForKey:@"entries"];
  }
  return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
  [aCoder encodeObject:_fields forKey:@"fields"];
  [aCoder encodeObject:_entries forKey:@"entries"];
}

我不能使用+ unarchiveObjectWithData:因为我需要设置一个委托来更新反序列化的对象:

- (id)unarchiver:(NSKeyedUnarchiver *)unarchiver didDecodeObject:(id)object {
  if([[object class] isSubclassOfClass:[LCEntity class]]) {
    [object setStore:_store];
  }
  return nil;
}

我正在使用ARC - 所以不要担心内存管理问题。

2 个答案:

答案 0 :(得分:0)

你能用这种方式实际使用归档器/ unarchiver吗?通常,您有一个已编码的根对象,它会对图的其余部分进行编码。请尝试使用以下内容:

- (NSData *)serialize:(id <NSCoding>)object {
    return [NSKeyedArchiver archivedDataWithRootObject:object];
}

- (id)deserialize:(NSData *)data {
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

当然,此时-serialize:和-deserialize:方法非常多余。他们的调用者应该直接调用NSKeyedArchiver / NSKeyedUnarchiver。


或者,您的编码对象或其子对象之一可能执行不良-initWithCoder:。这应该在堆栈跟踪中很明显。

答案 1 :(得分:0)

我可以通过在NSKeyedUnarchiverDelegate中返回对象来解决问题:

- (id)unarchiver:(NSKeyedUnarchiver *)unarchiver didDecodeObject:(id)object {
  if([[object class] isSubclassOfClass:[LCEntity class]]) {
    [object setStore:_store];
  }
  return object;
}

有点奇怪,因为Apple的文档声明如果你不想替换对象,你应该返回nil ...