はじめに
タイトルを悩んだが適切なタイトルの表現が難しい。
RealmSwiftのcreateOrUpdateことcreate(_:value:update:)
メソッドにおいて、update
パラメータに.modified
もしくは.all
を指定した場合かつプライマリキーを持つオブジェクトを更新する場合にその際の挙動について書いておく(後述するがCore Dataとほぼ同じ挙動だった)。
公式のリファレンスに従ってやや冗長に言い換えると、『主キーを持つオブジェクトによって既存を更新する場合は、新しいオブジェクト自体でプロパティが更新される』といったところかもしれない。
If an object already exists in the Realm with the specified primary key and the update policy is .modified or .all, the existing object will be updated and a reference to that object will be returned.
前提
- RealmSwift
- v10.12.0
(おそらくRealmの出た当初からこの挙動は変わっていないのであまり重要ではない)
createOrUpdate実例
nameプロパティにセットしない場合
まずRealm.Objectの説明から
class Person: Object {
@objc dynamic var id = 0
@objc dynamic var name: String? // この値をセットしなかったりしてみる
override static func primaryKey() -> String? {
#keyPath(Person.id)
}
}
このPersonのidを1にしたものを作成しnameをp1とする。そしてさらにid: 1を更新し、nameをセットしない。
func createPerson() {
let realm = try! Realm()
func debug(_ person: Person) {
print("---")
print("person.id:", person.id)
print("person.name:", person.name ?? "nil")
}
do {
let person = Person()
person.id = 1
person.name = "p1"
try! realm.write {
realm.create(Person.self, value: person, update: .modified)
}
debug(realm.object(ofType: Person.self, forPrimaryKey: 1)!)
}
do {
let person = Person()
person.id = 1
// person.name = "p1" // ここでセットしないことでどうなるのかを検証したい
try! realm.write {
realm.create(Person.self, value: person, update: .modified)
}
debug(realm.object(ofType: Person.self, forPrimaryKey: 1)!)
}
}
出力は次の通りとなり、新しいPersonによってデータがnameなしに上書きされたのがわかる。
---
person.id: 1
person.name: p1
---
person.id: 1
person.name: nil
- Person
- id
- 1
- name
- nil
- id
おわりに
(試せばわかると思うので)上記では細かく書いてないが、リレーションする内容もセットされていなければnameと同じようにnilになる。
関連
Core Dataはどうなるのか