ヒレガス本 第6章 アーカイブ
- Cocoaでの「アーカイブ」は、Javaとかで言う「シリアライゼーション」のこと。へー。
- アーカイブ「する」側と「される」側で、それぞれ実装していく。「される」側では「プロトコル」を実装する。ふむふむ。Objective-Cの「プロトコル」はJavaとかでいう「インターフェース」のことだって。なるほどね。
原文では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パターンということでいいのかな。
読み込み処理にも、同様に対応するクラスとメソッドが用意されている。解説は省略。