【Swift】Core Dataの使い方。Relationshipでエンティティ間に関係を持たせる。(Swift 2.1、XCode 7.2)
RelationShipとは
本記事では、Core Dataの機能のRelationShip(以下、リレーションシップ)について説明する。
リレーションシップとは、オブジェクトに他のエンティティのオブジェクトを把握させる機能である。
モデルを定義するときのAttributeの下に表示されている「Relationship」(下図赤枠)でこの機能を実装する。
正規化とは
リレーションシップが必要な理由を知る前に、正規化を知っておくと理解が深まると思うので、まずは正規化のイメージについて説明する。
下表の生徒一覧があったとする。一覧を見ると学校に在籍している生徒と所属部が分かる。この一覧には好ましくない点があるが分かるだろうか。
その通り。所属部の情報が冗長になっているのだ。例えば、野球部なら部費「32000円」、活動場所「花田球場」、活動日「火水」の同じ値が全部員に記入されている。
上記の状況には以下の欠点がある。
- 生徒を追加するたびに部活の全情報を設定しなければならない。
- 部活の情報を修正するときに、修正対象の部に所属する全生徒を修正しなければならない。
- 誰も所属していない部活を登録することができない。
そこで下図のように、生徒一覧から部活情報を切り出して「部一覧」を作成する。
先ほどの欠点が解消された。このようにデータ保存の無駄を省き、データを管理しやすくするのが正規化である。
ただし、一覧をただ真っ二つにするのではなく、生徒がどの部に所属しているのかの情報を生徒一覧に残し、あとでたどれるようにしておくのだ。
このように、データが他の一覧のデータを参照する関係がリレーションシップのイメージである。
リレーションシップを図にする
分割した一覧をオブジェクトで表現し、所属部から部一覧のオブジェクトに線を引くと下図のようになる。
生徒一覧の視点で見ると、生徒1人は部一覧のどれか1個を把握している。これを1対1関係(To One)という。
具体的なコードにしてみよう。
以下のコードは、生徒エンティティから作成した生徒クラス。注目なのは所属部の型がClubクラスになっていることだ。1つの生徒オブジェクトは1つの部活オブジェクトを持つことになる。
つまり、エンティティを作るときにリレーションシップを定義すると、別のエンティティのクラスをプロパティに持つことになる。
1 2 3 4 5 6 7 8 9 10 |
//生徒クラス extension Student { @NSManaged var number: NSNumber? //番号 @NSManaged var name: String? //名前 @NSManaged var age: NSNumber? //年齢 @NSManaged var club: Club? //所属部 } |
上記リレーションシップの逆のリレーションシップも定義できる。
部一覧の視点で見ると、1つの部は生徒一覧の複数個を把握している。これを1対多関係(To Many)という。
以下のコードは部活エンティティから作成した部活クラス。注目なのは部員の型がNSSetクラスになっていることだ。NSSetとは、複数オブジェクトを格納できる入れ物で「順序付け無し」、「重複できない」という特徴がある。
要するに、1つの部活オブジェクトは複数の生徒オブジェクトをプロパティに持つことになる。
1 2 3 4 5 6 7 8 9 10 11 |
//部活クラス extension Club { @NSManaged var name: String? //部名 @NSManaged var money: NSNumber? //部費 @NSManaged var place: String? //活動場所 @NSManaged var schedule: String? //活動日 @NSManaged var student: NSSet? //部員 } |
次記事で実際にリレーションシップを定義して使う流れを説明する。