【ISSUE】[Swift5] Realmのよく使うところだけをサンプル付きでまとめてみた
2024年12月23日 17:28
保存できる型
Bool
, Int
, Int8
, Int16
, Int32
, Int64
, Double
, Float
, String
, Date
, Data
.CGFloat
で保存することは推奨されない(できなくはないが型がRealmで保証されていない)
String
, Date
, Data
は Optional
指定 が可能。
その他の保存できる型で Optional
指定 をしたい場合は、RealmOptional
を利用する。RealmOptional
は「Int,
Float
, Double
, Bool
」に対応。
RealmOptional
プロパティは必ずlet
でなければいけない。
Realm
モデルに定義されるプロパティは@obj dynamic var
属性を持たなければならない。ただしSwift4
以降で利用することのできる@objcMembers
修飾子をクラスに宣言している場合、プロパティは単にdynamic var
属性で宣言することができる。
ただし、LinkingObjects
, List
, RealmOptional
属性は動的なプロパティとして宣言することができないので、常にlet
で宣言しなければならない。
Type | Non-optional | Optional |
---|---|---|
Bool | @objc dynamic var value = false | let value = RealmOptional<Bool>() |
Int | @objc dynamic var value = 0 | let value = RealmOptional<Int>() |
Float | @objc dynamic var value: Float = 0.0 | let value = RealmOptional<Float>() |
Double | @objc dynamic var value: Double = 0.0 | let value = RealmOptional<Double>() |
String | @objc dynamic var value = "" | @objc dynamic var value: String? = nil |
Data | @objc dynamic var value = Data() | @objc dynamic var value: Data? = nil |
Date | @objc dynamic var value = Date() | @objc dynamic var value: Date? = nil |
Object | n/a | @objc dynamic var value: Class? |
List | let value = List<Type>() | n/a |
LinkingObjects | let value = LinkingObjects(fromType: Class.self, property: "property") | n/a |
モデルを定義する時に primaryKey
メソッドをオーバーライドすることで、モデルの主キーを設定することができる。主キーを設定したオブジェクトをRealm
に保存すると、後から変更することができない。
Realm
では各モデルでプロパティのインデックスをindexedProperties
メソッドをオーバーライドすることで作成できる。インデックスを作成することで、等号演算、IN演算しを用いたクエリを高速に実行することができる。(※ インデックスを作成するため Realm
ファイルのサイズは大きくなる)
Realm
ではString
, Int
, Bool
, Date
型プロパティのインデックスに対応している。
Realm
に保存する必要のない変数(一時使用、一時的な変数)をignoredProperties
メソッドをオーバーライドすることで設定できる。これを設定することでプロパティとして操作、利用することができるが、保存する際にデータは無視される。また、getterしか持たない変数は、自動的にモデル保存時に無視される。
モデルを書き込むためには、モデルオブジェクトをインスタンス化してRealm
に追加する必要がある。
Dictionary
を用いて、初期化して作成する方法Array
を用いて、初期化して作成する方法モデルオブジェクトを作成後、Realm
に追加することができる。
Realm
への書き込みトランザクションが終了すると、他のスレッドでも追加した値を利用することができるようになる。このとき、複数の書き込みが同時進行で発生した場合は、他方の書き込みが終わるまでロックされる。これによって書き込みがロックされているスレッドもロックされることを注意する必要がある。
ただし、書き込みトランザクションが終了していない場合であっても、読み込みは可能である。
モデル更新の方法は複数ある。
プライマリキーを設定している場合は、プライマリキーによる更新を行うことができる。
この時、主キー(id: 1)がすでに存在していれば単に更新処理が走る。主キーが存在しない場合は create
と同等の処理が実行される。また、主キーと更新したい値のサブセットを引数にすることで差分更新を行うことができる。
ただし、主キーを定義していないモデルオブジェクトを更新する場合には update:
の引数に .modified
, .all
を渡すことができない。また、.modified
, .all
を使った多重(コンフリクトが発生するような)書き込みの結果には注意が必要。
この場合、2つの更新が同時に発生するためコンフリクトが発生する。これらの書き込みがマージされた結果として得られる結果は、以下のどちらかとなる。
しかしupdate: .modified
とした場合は、挙動が変わる。
この場合の書き込みがマージされた結果は以下のようになる
.all
は完全置き換え、.modified
は差分置き換えであることを注意する必要がある。
書き込みトランザクションの中で以下を実行する。
Realm
のオブジェクトインスタンスは自動的に更新される。つまり、オブジェクトのプロパティを変更すると、同じオブジェクトを参照している他のインスタンスに、その変更が即座に反映される。Realm
オブジェクトの更新通知を購読することで、対象のRealm
オブジェクトに変更があった場合に通知を取得できる。
Realm
ではLinkingObjects
を用いることで、双方向リレーションを形成することができる。LinkingObjects
は特定のプロパティ(ここではPersonモデルのdogsプロパティ)から与えられたオブジェクトにリンクされているすべてのオブジェクトを取得することができる。Realm
は直接JSONをサポートしていないが、JSONSerialization
の出力を用いでオブジェクトを生成することができる。JSON内にネストされてるオブジェクトや配列は、自動的にリレーションにマッピングされることに注意する必要がある。
この方法でオブジェクトを生成するときには、いくつかの注意点が存在する。
オブジェクトのプロパティ名とJSONのキー名が一致して、型が同じである必要があります。
floatプロパティは、floatをバックにしたNSNumbersで初期化する必要があります。
DateプロパティとDataプロパティは文字列から自動的に推論することはできませんが、Realm().create(_:value:update:)に渡す前に適切な型に変換しなければなりません。
必須プロパティに JSON NULL (すなわち NSNull) が与えられた場合、例外がスローされます。
insert 時に必須のプロパティが与えられない場合は、例外がスローされます。
Realmは、Objectで定義されていないJSON内のプロパティを無視します。
Realm
では Realm
に書き込まれたか否かで、更新方法が変わる場合がある。
Realm
に書き込まれる前のオブジェクト( realm.write
クロージャーの外でプロパティを変更できる)
Realm
に書き込まれた後のオブジェクト (realm.write
クロージャーの外でプロパティを変更できない)
一般的には、このように分離して処理を変更するべきであるが、以下のようにすることもできる。
[cv:issue_marketplace_engineer]
診断を受けるとあなたの現在の業務委託単価を算出します。今後副業やフリーランスで単価を交渉する際の参考になります。また次の単価レンジに到達するためのヒントも確認できます。