【SwiftUI】Realmでプライマリーキーの設定方法!UUIDを指定

この記事からわかること
- Realm Swiftでプライマリーキーを扱う方法
- Swift UIでの実装方法
- UUIDを使った重複しないキー指定
- ObjectIdを使った重複しないキー指定
- エラー:Attempting to create an object of type 'クラス名' with an existing primary key value '値'.
- エラー:\'クラス名\' does not have a primary key and can not be updated"
- エラー:Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=10 "Migration is required due to the following errors:
index
[open]
\ アプリをリリースしました /
モバイル向けのデータベースを提供しているRealm Swiftの扱いの中でプライマリーキーを設定する方法をまとめていきます。
Realm Swiftでプライマリーキーを設定する方法
Realm Swiftはデータベースなのでプライマリーキーを指定することも可能です。プライマリーキーとは指定したカラムに重複した値が入らないようにするための設定です。
設定するにはテーブルクラスを定義する際にprimaryKey
メソッドをオーバーライドしてプライマリーキーに指定したいプロパティ名をリターンします。
これでid
にはプライマリーキーが重複した値を持つオブジェクトの格納が許可されなくなりました。
@Persistedのイニシャライザから設定する
プロパティラッパーの@Persisted
のイニシャライザを使用することでもプライマリーキーを設定することが可能です。
Attempting to create an object of type 'クラス名' with an existing primary key value '値'.
しかしこの状態であえて重複した値を持つオブジェクトを入れ込もうとすると以下のようなエラーが発生し、アプリが停止してしまいます。
これを解決する方法はaddメソッドの定義に載っていました。
引用:addメソッドの定義
”オブジェクト型に主キーがないか、指定された主キーを持つオブジェクトがない場合 既に存在する場合、レルムに新しいオブジェクトが作成されます。レルムにオブジェクトがすでに存在する場合 指定された主キーと更新ポリシーが `.modified` または `.all` の場合、既存の オブジェクトが更新され、そのオブジェクトへの参照が返されます。”
なのでアプリが落ちてしまうのを防ぐためにadd
メソッドの引数にupdate:.modified
を指定します。これで重複したオブジェクトを新規で追加することなく、一致したキーのデータを新しいオブジェクトで更新してくれます。
これで上記のボタンを何度押してもアプリが落ちることはなくなります。
\'クラス名\' does not have a primary key and can not be updated"
逆にプライマリーキーを指定せずにupdate:.modified
を指定してしまうと以下のようなエラーが発生してしまうので注意してください。
UUIDを使った一意のID
上記では一意の値のみを許可したid
プロパティをString
型で定義していましたが、Realm SwiftではUUIDも使用可能です。
おすすめ記事:【Swift UI】UUIDとは?使用方法
SwiftではUUIDが128bit(=16byte)の数値として表されデータ型はUUID型になります。指定する際はUUID
構造体をインスタンス化して初期値に指定すればOKです。
これで追加するたびに一意のid値が生成されるので、重複を気にすることなく使用可能になります。
ObjectIdを使った一意のid
UUIDと同様に初期値として一意の値を付与できる方法にRealm Swiftライブラリで使用できるObjectId
があります。これは12バイトの一意の英数字の羅列が生成されます。またこの識別子でソートをかけると生成された順番に整列されるように割り振られます。
これで追加するたびに一意のid値が生成されるので、重複を気にすることなく使用可能になります。
途中でプライマリーキーを追加するとエラーになる
プライマリーキーを最初指定しないまま使用していた場合に後からプライマリーキーを指定してしまうと以下のようなエラーになってしまいます。
これは定義済みのRealmクラス(テーブル定義)と保存されているRealmオブジェクト(テーブル内のレコード)の定義が不一致を起こすためです。
この場合は一度アプリ自体をデバイスから削除するかマイグレーションを使用することで解決できます。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。