【Swift】Core Dataの設定。リレーションシップの削除ルールや参照タイプを設定する(Swift 2.1、XCode 7.2)
Relationshipの設定
本記事ではRelationship(以下、リレーションシップ)のデータモデルインスペクタの設定項目について説明する。
リレーションシップの使い方については前回記事を参照されたし。⇒「前回記事」
設定画面を開くには下図赤枠の「プロジェクト名.xcdatamodeld」を選択、黄緑枠のエンティティを選択、黄枠のリレーションシップを選択、紫枠のデータモデルインスペクタボタンを押す。
Name
リレーションシップの名前を設定する。
左側のリレーションシップ一覧の項目「Relatiohship」と同じ値になる。紛らわしいので左側の項目名はNameにした方がいいような気がする。
Transient
チェックを入れると外部ファイルに保存されない一時的なリレーションシップになる。考え方はAttributeのTransientと同じなので、詳細は次の記事を参照されたし。⇒「Attributeの記事」
Optional
必須項目、任意項目のどちらにするかの設定。チェックを入れると任意項目になり、値を設定しなくてもエラーは発生しない。デフォルトはチェックが入っている。
Destination
参照先のエンティティを指定する。例えば、下図の生徒エンティティの参照先は部活エンティティになる。
Inverse
反対方向のリレーションシップを指定する。例えば上図の「生徒から部活へのリレーション」の反対方向のリレーションは「部活から生徒へのリレーション」になる。
これを設定しておけば一方のリレーションを更新したときに、反対方向のリレーションも自動で更新してくれる。
Delete Rule
オブジェクトを削除するときのルールを「No Action」、「Nullify」、「Cascade」、「Deny」から選択する。不要なデータを残したり、データの不整合を発生させないためにも、この設定はよく考えて設定する必要がある。
1つずつ確認しよう。
No Action
オブジェクトを消しても参照先のオブジェクトには何も起きない。なので逆方向のリレーションシップに存在しない参照先が残り続ける。
例えば、下図の中西さんを削除したとき、逆方向のリレーションシップで中西さんを参照している野球部は、中西さん削除後も中西さんの参照先を持ち続ける。
そのため、野球部のリレーションシップを利用するときに、存在しないオブジェクトを参照しようとする。
Nullify
オブジェクトを消したときに参照先のオブジェクトの逆方向のリレーションシップをnilにする。
例えば、下図の中西さんを削除したとき、逆方向のリレーションシップで中西さんを参照している野球部は、中西さん削除とともに中西さんを参照先しなくなる。よって、データの整合性は保たれる。
Cascade
オブジェクトを消したときに参照先のオブジェクトも一緒に削除される。
例えば、下図の中西さんを削除したとき、参照先の野球部も一緒に削除される。そのため、佐藤さんのリレーションシップを利用するときに、存在しない野球部のオブジェクトを参照しようとする。
Deny
他のオブジェクトを参照している状況でオブジェクトを削除しようとするエラーが発生する。
例えば、下図の中西さんを削除しようとしても中西さんは野球部を参照しているため削除することはできない。
では、生徒から野球部へのリレーションシップのDelete Ruleは4つの選択肢のうちどれが適しているかを考えてみる。
- 生徒オブジェクトは追加、削除されることがある。
- 部活に所属している生徒は一人とは限らないので、生徒オブジェクトを削除したときに野球部オブジェクトは残す必要がある。
- 生徒オブジェクトを削除したときに、野球部オブジェクトから生徒オブジェクトへの参照も削除する必要がある。
上記を考慮すると、「Nullify」が適しているという結論になる。
Type
参照先のオブジェクトの数を「To One(1つ)」と「To Many(複数)」から選択する。
例えば下図の場合、生徒オブジェクトが参照する部活オブジェクトの数は1つなので「To One」を設定する。一方、部活オブジェクトが参照する生徒オブジェクトの数は複数あるので逆方向のリレーションシップには「To Many」を設定する。
「To One」を設定してエンティティのサブクラスを作ると、以下コードの「所属部」のように、参照先のクラスを型とするプロパティが生成される。オブジェクトは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? //所属部 } |
「To Many」を設定してエンティティのサブクラスを作ると、以下のコードの「部員」のように、NSSet型のプロパティが生成される。オブジェクトは複数のオブジェクトを参照するということだ。
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? //部員 } |
「To Many」に設定すると下図赤枠の設定項目が追加される。
Arrangement
先ほどはNSSet型のプロパティが生成されたが、Orderedにチェックを入れてエンティティのサブクラスを作るとNSOrderSet型のプロパティが生成される。
NSOrderSetは順序付けらて重複を許さないセットなので、管理オブジェクトコンテキストに格納した順番にデータを取り出すことができるようになる。
1 2 3 4 5 6 7 8 9 10 11 |
//部活エンティティ extension Club { @NSManaged var clubName: String? @NSManaged var money: NSNumber? @NSManaged var place: String? @NSManaged var schedule: String? @NSManaged var student: NSOrderedSet? } |
Count
参照先オブジェクトの個数の最小値と最大値を設定する。条件を満たさない状況でsaveメソッドを呼び出すとエラーが発生する。