0

decodeObjectForKey: 呼び出しで 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 を使用しているので、メモリ管理の問題について心配する必要はありません。

4

2 に答える 2

0

実際にアーカイバー/アンアーカイバーをそのように使用できますか? 通常、エンコードされたルート オブジェクトがあり、それがグラフの残りの部分をエンコードします。以下を使用してみてください。

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

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

もちろん、この時点で -serialize: および -deserialize: メソッドはかなり不要です。それらの呼び出し元は、NSKeyedArchiver/NSKeyedUnarchiver を直接呼び出す必要があります。


あるいは、エンコードされたオブジェクトまたはそのサブオブジェクトの 1 つに、 の実装が正しくない可能性があり-initWithCoder:ます。これは、スタック トレースで明らかになるはずです。

于 2012-08-10T22:20:04.590 に答える
0

NSKeyedUnarchiverDelegate で常にオブジェクトを返すことで問題を解決できました。

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

Apple のドキュメントでは、オブジェクトを置き換えたくない場合は nil を返す必要があると述べているため、少し奇妙です...

于 2012-08-11T00:33:42.287 に答える