前回のエントリで、強引ではありますが、RDBMSデータベースアクセスとCore Dataの関係をまとめました。何となくではありますが、WindowsでRDBMSデータベースアクセスのアプリケーションを作った事がある人はぼんやりとイメージがつかめるのではないでしょうか?今回も引き続きCore Dataについて書きます。
◎Core Dataにおける1対多の関係
XcodeでCore Dataを使う場合に一番簡単な方法は、Master-Detail Applicationテンプレートを使用することです。このテンプレートを使えば、一覧表示する為のUITableViewControllerと項目の編集を行う為のUIViewControllerを自動生成してくれるので、そのコードを一つ一つ見ていけば、前回のエントリで書いたようなCore Dataの大まかな動きが理解できると思います。
ただ、このテンプレートでは、例えば「音楽アルバムの収録曲一覧を表示する」といったことはできるのですが、「最初にアルバム名一覧があって、タップするとそのアルバムの収録曲の一覧を表示する」といった1対多の関係を表示することはできません。
[RDBMSに対するデータベースアクセスの場合]
やり方は色々あると思いますが、今までよくやってきたのは次のような感じです。
テーブル:(1)アルバムテーブル。項目はアルバムコードとアルバム名。主キーはアルバムコード。(2)楽曲テーブル。項目はアルバムコード、曲コード(曲順)、曲名、歌手名。主キーはアルバムコード、曲コード・・・とする ※この例だと楽曲テーブルにアルバム名持たせて管理するという方法でもいいですが、ここはあくまで例ということで。
取得方法その1:最初にアルバムテーブルからアルバム一覧を取得。アルバムが選択された段階でそのアルバムの収録曲一覧を取得する
取得方法その2:SQLでアルバムテーブルと楽曲テーブルを結合して一度にまとめて取得する
更新方法:対象のテーブルに対して、SQL(INSERT/UPDATE/DELETE)を実行する
[Core Dataの場合]
テーブル:(1)アルバムエンティティ。項目はアルバムコードとアルバム名、楽曲一覧(※)。(2)楽曲エンティティ。項目はアルバムコード、曲コード(曲順)。アルバムテーブルと楽曲テーブルの関連付けを1対多で行っておく必要がある ※アルバムエンティティをNSManagedObjectのサブクラス(アルバムクラス)として定義する場合、楽曲一覧はNSSetクラス(楽曲クラスの集合)として定義されます。
取得方法:アルバムエンティティを指定してNSFetchRequestオブジェクトを抽出する。この段階でアルバムクラスの楽曲一覧にはアルバム収録曲の一覧(楽曲クラス)が格納されている
更新方法:追加/変更の場合は、取得したNSManagedObject(アルバムクラス)を変更した後、NSManagedObjectContext saveメソッドでコミットするとよい。ただし、削除の場合は、アルバムクラスから削除するのではなく、楽曲クラスに対しNSManagedObjectContext DeleteObjectメソッドでエンティティ本体の削除を行う必要がある。
ここでハマったのは次の3点。
・Core Dataで定義するエンティティには主キーがないということ。エンティティ間を1対多の関係にするには、各エンティティのRelationshipを相互に設定し、かつ、親エンティティ側のTo-Many Relationshipにチェックを入れておく必要があります。
・今回エンティティと連動させるクラスにNSManagedObjectを継承したサブクラスを使ったのですけど、子エンティティのオブジェクトの型をどうするかで悩みました。正解はNSSetクラス。これは、XcodeのNSManagedObject subclassテンプレートを使えば、クラス定義まで自動生成してくれます。つまりテンプレートを使わずにサブクラスを作ろうとしてハマったということですね(^^;。
・上記にも書いたように、子エンティティ(楽曲エンティティ)の削除の仕方。アルバムクラスの楽曲一覧から楽曲クラスを削除してsaveすると、再起動した時に削除したはずの楽曲クラスが再び表示されました。これを削除するには、アルバムクラスを操作するのではなく、削除対象の楽曲クラスを指定してDeleteObjectメソッドで削除する必要があります。
◎Core Dataと画面遷移
次は画面間において、取得したNSManagedObjectをどのように共有するかです。これもMaster-Detail Applicationテンプレートを見れば大体分かると思います。prepareForSegueというdelegateメソッドで、対象となるNSManagedObject(またはサブクラス)とNSManagedObjectContextオブジェクトを呼び出す画面に渡します。これは、RDBMSに対するデータベースアクセスの場合に画面間でConnectionオブジェクトとRecordsetオブジェクトを引数として渡すのと同じです。呼び出された画面側では対象となるNSManagedObjectを編集して、最終的にNSManagedObjectContext saveメソッドでコミットするとデータベースが更新されます。
・・・以上が、私がCore Dataを勉強していてハマった部分の覚え書きです。(ピンポイント過ぎて全然説明になっていない気もしますが(^^;。)最後に今回Xcode 4.2でCore Dataを勉強するのに参考にさせていただいたサイトを挙げておきます。勝手ながらここでお礼をさせていただきます。
サルでもわかる Core Data 入門【概念編】(@glassonion1さんのブログ)
⇒概念編と実装編を画面のハードコピー付きで解説されています。Xcode 4.2ベースでStoryboardも使用されているのですぐに実践できます。
『iOS Core Dataチュートリアル』を、Xcode4.2 + Lion で学ぶ。(@toaster4usさんのブログ)
⇒『iOS Core Dataチュートリアル』はApple社が提供するドキュメント・・・なのですが、最終更新日が2010/11/15と古く、Xcode 4.2でそのまま組もうとしても正しく動きません・・・が、このブログではタイトル通りXcode 4.2上で『iOS Core Dataチュートリアル』を実践されています。Xcode 4.2で勉強を始めた者にとってはとても助かる内容です。