うるおいらんど

アプリ開発やサイト制作のメモとか。

【Swift 3】CoreDataをつかってみた。Relationshipをつけよう【part 3】

魚ライン
魚ライン

どうも。part3です。

part1,2はそれぞれ以下よりどうぞ。

【Swift 3】CoreDataを使ってみた【part1】

【Swift 3】CoreDataを使ってみた。検索・更新・削除編【part2】

 

今回はRelationshipをつけていきます。

 

Relationshipとは

Relationshipとは、Entity間で関係を持たせることです。

CoreDataは「関係データベース(Relational Database)」の類ですし、それぞれのEntityに関係を持たせることができます。

「関係データベース」ってなんだ?って人はまずはそこから勉強すると良いと思います。

エラそうに言っていますが、私もFE(資格)の勉強をする時にやっただけで、実際に触ってみるのは初めてです!

 

少しだけ説明しておこうと思います。

関係データベースとは

関係データベースは、データを行と列による2次元の表で表し、複数の表を組み合わせてデータを管理します。

こんな感じのやつです

relation

関係データベースには「主キー」と「外部キー」があります。

主キーと外部キー

主キーは「行を一意に識別するための列」のことをいいます。

つまり「データの値が空でなく、なおかつ決して重複しない列」のことです。

この主キーがあることによって確実にデータを識別することができます。

 

外部キーは「他の表の主キーを参照する列」です。

relation2

 

別の表の主キーとなっているデータが格納されています。

 

CoreDataを使用するときも同様に、1つのEntityに必ず1つ主キーにあたるものを作成してください。

外部キーはRelationshipを指定するときに必要です。

 

 

正規化とは

正しくデータが管理できるような表を作ることを正規化といいます。

 

関係データベースでは、表をいくつも組み合わせてデータを管理しています。

それぞれの表の主キーや外部キーが変更された際には、他の表にも反映しなくてはなりません。

そうしなければ、データに矛盾や重複が発生しています。

正規化することで、データの矛盾や重複を取り除くことができます。

seikika

 

正規化をすすめると、上のようにいくつもの表に分けることになるので、毎回表の結合をする必要が出てくるので、アクセス効率はむしろ低下してしまいます。

 

厳密にいうと上記表の上側の表も正規化された表になります(第2正規形)。おそらく下の表も、担任→教室の部分が別表に分けられると思いますので、第2正規形なのかな・・・。

 

ちなみに正規化されていない表というのは下のようなものになります。

seiki

 

下は第1正規形となります。

正規化は

1.繰り返し項目がある(非正規形)

2.繰り返し項目を取り除く(第1正規形)

3.主キーによって他の項目が決まるように分別(第2正規形)

4.主キー以外の項目によっても決定される項目を分別(第3正規形)

といった流れになります。

 

 

CoreDataで複数の表をつくろう

長くなりましたが、やっとCoreDataの方をやっていきます。

CoreDataで上記の「学生表」と「担任表」を作っていこうと思います。

 

まずはEntityを作成していきます。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-8-59-21

Add Entityより2つのEntityを作成します。

このEntityの名前は表のタイトル(学生表/担任表)だと思うとわかりやすいかなと思います。

 

StudentとClassにそれぞれAttributeを付け加えていきます。

Student

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-9-09-48

Class

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-9-05-19

 

Attributesは上記表の「学籍番号 / 氏名 / クラス」の部分になります。

 

Relationshipをつけよう

StudentとClassにRelationshipをつけていきます。

 

 

まずは Student側

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-9-16-36

 

Class側

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-9-17-36

 

Student側に付け足した「studentClass」は先ほど説明した外部キーになります。

私は「AttributeがstudentClassでTypeがClass」といった覚え方をしています。分かりづらいですが、このstudentClassもその他のnameとかと同じように扱うといった認識をしています。。

 

Class側は「Student表にあるstudentClassから参照されているよ」といった関係がつけられています。

 

relation4

 

間違った認識だったら教えて下さい(´;ω;`)

 

1対1、1対多の関係

CoreDataのRelationshipといったらこの「1対1の関係」「1対多の関係」「多対多の関係」といった言葉をよく聞きますよね。

これはつまりこういうことだと思っています。

relation6

 

「相田あい」の担任は「坂井聡」です。そのほかに担任はいません。なのでこれは1対1の関係。

反対に

「坂井聡」の担任するクラスの学生は「相田あい」以外にもたくさんいます。なのでこれは1対多の関係。

 

これをCoreDataで関係をつけていきます。

 

 

Student

右側のRelationshipよりType > To Oneを選択

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-9-53-38

 

Class

右側のRelationshipよりType > To Manyを選択

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-10-05-41

 

これでDataModelの設定は完了です。

 

Editor > Create NSManagedObject Subclassよりサブクラスを作成しておいてください。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-17-10-01-05

 

 

 

データを保存しよう

データを保存していきます。全体のコードから

 

かるく説明をしていきます。

 

まず最初に、Classの方にデータをいれておきます。

 

次にStudentを登録していきます。

 

そして、StudentとClassを紐付けます

 

すでにあるクラスに登録する場合は最初のクラスの登録はしなくていいです。

紐づけるときに、クラスが存在しない場合はstudentClassには何も挿入されません(nilになる)

 

紐付けはおそらく

だけでおkです。

上記だと、まだデータの保存ができていないのでfetchDataは必ず空になっているのではと思います。。。

(2017/03/15日追記)

 

データを呼び出そう

データを呼び出すときはRelationshipをつけていないときとほとんど同じです。

 

例えば、「相田あいさんの担任が知りたい」とき

 

通常のAttributeとそんなに変わらず使えます。

ただこれはあんまり良くない調べ方だと思います(相田あいという名前が重複している可能性があるため)

 

 

反対に、「坂井聡さんが担任をするクラスの生徒」を表示するとき

この場合

といった書き方はできません。

 

クラスの人数を調べる場合は簡単にできますが、

クラス側からの場合は、student個人の変更はできません。(できるかもですが面倒そう・・・)

—-(2017/09/08追記)—–

クラス側からstudentの情報を取り出すときは取得したfetchData[i]の情報を使えば取得できます。

上記のfor文の中は[Class]の中身を1つずつ取り出しているのでfetchData[i]はClassの情報が入っています。

なのでfor文の中で

と、Studentを探して来てやればおkです。

このときClassに紐づいているStudentを全て取得する場合(この場合だと坂井聡さんが担当しているクラスの生徒)、predicateのフォーマットの部分でfetchData[i]を用います。

この”studentClass”というキーは、モデルを作ったときに設定した外部キーってやつです。

ファイルを見た方がわかりやすいかもしれない。



この studentClass:Class?ってなってるやつですね。

 

(改めて読んでみると、このときはfor in文で配列の中身を1つずつ取り出す方法も知らなかったっぽいですね。あとはひっそり読み込みの方の保存方法がおかしかったのを修正しました。更新してなければ呼ぶ必要はないところなので支障はなかったと信じる・・・)

——————————–

 

データを削除しよう

studentの中から1人を削除する場合は通常と同じ方法でOKです

 

このときClass側からの参照も削除されているはずです。(設定によってはされないらしい)

 

Classを削除する場合は

 

この場合1Aというクラスは削除されますが、1Aに所属しているStudentは削除されません。

studentClass = “1A”の生徒は studentClass = nil となってしまいます。

 

 

CoreDataについてはとりあえずこのパートで終わる予定です。

また何かあったら個別に書いていこうと思います。

 

長くなってしまいましたがなんだかそんなにうまく説明できた気もしないです。。。

 

参考

CoreDataについては、「はじはじアプリ製作体験記」さんの記事が個人的にはすごくわかりやすくて大変参考になりました。ありがとうございます。

細かい設定などに関しても詳しく書かれていますのでぜひぜひ。

【Swift】Core Dataの使い方。編集データを外部ファイルに保存する。これを使えば大量データも怖くない。

 

 

魚ライン
モッピー!お金がたまるポイントサイト
魚ライン

Swiftの記事一覧を見る

コメント

コメントは認証制です。詳しくは下記の注意をお読みください。

コメントを残す

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

魚ライン 魚ライン