ヒレガス本 第6章 アーカイブ

原文ではNSCoderつまりアーカイブ「される」側から解説してあるがここではNSArchiverつまりアーカイブ「する」側からみていく。

// MyDocument.m
- (NSData *)dataRepresentationOfType:(NSString *)aType
{
	NSLog(@"dataRepresentationOfType: %@", aType);
	[tableView deselectAll: nil];
	return [NSArchiver archivedDataWithRootObject: employees];
}
  • ビューなどから保存機能がキックされると、dataRepresentationOfTypeが呼ばれる。この中で、指定されたタイプの(メモリ上の)データ表現を返す。
  • このために、NSArchiverクラスのarchivedDataWithRootObjectメソッドが用意されている。保存したいオブジェクトをこのメソッドに渡すと、NSCodingプロトコルに従って再帰的にデータ表現が構成されていくらしい。
// Person.m
- (void)encodeWithCoder: (NSCoder *)coder
{
	[coder encodeObject: personName];
	[coder encodeValueOfObjCType: @encode(float) at: &expectedRaise];
}
  • 保存対象のクラスでは、NSCodingプロトコルのencodeWithCoderメソッドを実装しておく。
  • このメソッドには、実際のエンコードを担当するNSCoderクラスのインスタンス(coder)が渡されてくるので、深く考えずにcoderのencodeObjectメソッドやencodeValueOfObjCTypeメソッドを使ってエンコードすればよい。
  • 極論すれば、ここで考える必要がある(選択の余地がある)のは、どの順番でオブジェクト(親クラスを含めたインスタンス変数)をエンコードするかだけである。
  • この例では、employeesはNSMutableArrayなので、まずNSMutableArrayのencodeWithCoderが呼ばれる。おそらくこの内部で配列要素(Personクラスのインスタンス)それぞれのエンコード処理が記述され、そこでようやくencodeWithCoderが呼ばれるという流れになるのだろう。これはGoFでいうVisitorパターンということでいいのかな。

読み込み処理にも、同様に対応するクラスとメソッドが用意されている。解説は省略。

最終的にはCore Data使うか、Rubyyamlとか使っちゃうかになると思うので、RubyCocoa版も省略。