【Swift】Core Dataの設定。エンティティに複合インデックスや一意制約を付与する。(Swift 2.1、XCode 7.2)

2020年6月16日

Entityの設定

本記事は、前回記事「Entityの設定」の続きである。⇒「前回記事

Entityの設定

 

Indexes

インデックスを作る属性を指定する。インデックスとは、データ検索を高速化するための索引のことである。

例えば下図のように、データが無秩序に並んでいる中から3を探す場合、全領域に3が存在する可能性があるので、すべてデータを確認する必要がある。これがインデックスが作成されていない状況。

下図のような少ない件数であれば問題ないが、これが何千、何万という件数になったらかなり時間がかかりそうなのは想像に易い。

インデックス無しの全件走査

 

上記のデータが下図のように数字の小さい順に並んでいた場合、検索データから後ろのデータは確認する必要がなくなる。これがインデックスを作成したイメージである。何千、何万という件数なら大幅に検索時間を短縮できる。

なお、これはインデックスを説明するためのイメージ図であり、実際にこのように並ぶわけではない。

インベックスを作成してデータを検索

 

インデックスには単一インデックスと複合インデックスがあるが、Indexesの設定項目は、主に複合インデックスを定義するのに使われる。単一インデックスは属性ごとの設定画面からも設定できる。

単一インデックスとは、1つの属性をキーにしてデータを検索するときに使われるインデックスである。例えば「name=’佐藤’」で検索するときは、属性nameのみ使われるので単一インデックスである。

複合インデックスとは、2つ以上の属性をキーにしてデータを検索するときに使われるインデックスである。例えば「name=’佐藤’ かつ age=20」で検索するときは、属性nameとageが使われるので複合インデックスである。

複合インデックスを定義してみよう。下図赤枠の「+」ボタンを押すと「comma,separated,propaties」の行が追加されるので、その行をクリックして値を変更可能にし、「name,age」を入力する。

インデックスを追加する

 

1つ不思議な事象が発生した。

Indexesに「hoge,hoge」などの存在しない属性名を入力してもエラーが検出されずにシミュレーターが正常に起動してしまうという事象だ(Swift 2.1、XCode 7.2)。

その場合、Abstract Entityなどの他の設定項目の値を変更すると、それに反応してIndexesに入力した値が確定し、エラーが検出されるようになった。

indexesに存在しない属性名を設定

 

インデックスはデータ検索を高速化させる利点がある一方、データが追加されるたびにインデックスの更新が実施されるので、データ追加が頻繁に行われるエンティティにインデックスをたくさん定義すると、データ追加時の処理時間が長くなってしまうので注意されたし。

Constraints

ここに追加した属性はデータが重複できなくなる(一意制約)例えば、nameが「佐藤」のデータ2つを保存しようとすると、2つ目のデータを保存するタイミングでConflict(衝突)のエラーが発生する。

Error Domain=NSCocoaErrorDomain Code=133021 “(null)" UserInfo={conflictList=(“NSConstraintConflict (0x7b9708d0) for constraint‥}

 

組み合わせた属性値を重複させたくない場合は属性名をカンマ区切りで入力する(例、name,age)。

実際にConflictを発生させてみよう。

下図赤枠の「+」ボタンを押すと「comma,separated,propaties」の行が追加されるので、その行をクリックして値を変更可能にし「name」を入力する。

Constraintsに属性を追加する

 

ViewController.swiftを以下のコードに変更する。エラーが発生したら、エラーの内容をアラート表示するようにした。

 

以下は実際のプレイ動画。

なお、Indexesの場合と同様に、Constraintsに値を設定した直後は設定が反映されていない。シミュレータを起動して同じ文字列を2回入力してもコンフリクトが発生しない場合は、Abstract Entityなどの他の項目の値をオンオフしてから起動してみるのを試してほしい。

 

エラーを発生させないで、コンフリクトが発生したデータをマージさせる場合は、以下のコードのように管理オブジェクトコンフリクトのマージポリシーを変更する。⇒「参考サイト

マージが実施されるのは、管理オブジェクトコンテキストにオブジェクトを格納したときではなく、saveメソッドを呼んだタイミングで実施される。

 

変更を破棄する場合は以下のコードにする。

 

User Info

エンティティの設定の下にUser Infoという設定項目がある。

User Infoとは、項目につける付加情報のことで、エンティティの設定の下にあるUser Infoは、選択しているエンティティにつける付加情報である。

User Infoの設定項目

 

実際にエンティティにUser Infoを追加し、ソースコードで値を取り出してみよう。

下図赤枠の「プロジェクト名.xcdatamodeld」を選択、黄緑枠のPlayerエンティティを選択、紫枠のデータモデルインスペクタボタンを押して設定画面を表示する。

水色枠の「+」ボタンを押してUser Infoの行を追加する。Keyに「testKey」、Valueに「スポーツ選手」を入力する。

エンティティにUser Infoを追加する

 

ViewController.swfitの「Returnキー押下時の呼び出しメソッド」に以下のコードを追加する。

testKeyに紐づく値をUser Infoから取り出しラベルに設定している。

 

以下は実際のプレイ動画