Realmはカスケードデリートができないので、自分で削除する必要がある。
自分はこうした、という話。
環境
- RealmSwift 2.4.1で確認しています。
参考モデル
- BrandとShopがある
- Brand 1:n Shop の関係
- Brandを削除する際はShopも削除されてほしい
Brand.swift
class Brand:Object {
dynamic var id = ""
dynamic var name = ""
let meals = LinkingObjects(fromType: Shop.self, property: "group")
}
Shop.swift
class Shop:Object {
dynamic var id = ""
dynamic var name = ""
dynamic var brand: Brand?
}
とりあえず消す書き方
let realm = try! Realm()
let brand = try! Realm().objects(Brand.self).first
realm.begin()
realm.delete(brand.shops)
realm.delete(brand)
try! realm.commitWrite()
この、とりあえず消す書き方をしていると辛くなるときが来る。
辛くなる兆候
- 各所でとりあえず消す書き方をしている
- モデルが複雑になるときがきた
- 子要素の子要素になるモデルが作られた
とりあえずの箇所 * 子要素の数
だけ手間が増えてしまう。
プロジェクト内一括置換でまぁ対処できるけどdeleteの順序とかルール化しないと漏れが発生すると思う。
プロトコルを定義して実装させる
protocol DeletableChildren {
func deleteChildren(from realm:Realm)
}
Brand.swift
// 実装を加筆
extension Brand: DeletableChildren {
func deleteChildren(from realm: Realm) {
realm.delete(self.shops)
}
}
実装後の消し方
一応。
let realm = try! Realm()
let brand = try! Realm().objects(Brand.self).first
realm.begin()
brand.deleteChildren(from: realm)
realm.delete(brand)
try! realm.commitWrite()
何が嬉しい
- 子要素が増えても編集箇所を1箇所で済ませられる
- モデルに子要素削除を実装したことで、削除しなきゃならない子要素を見逃しにくくなった
まぁ、変更箇所は少ない方が良いし、兆候に気づいたら先手打ちたくなるよね。
参考URL
2017-02-15現在、カスケードデリート審議中の模様。
https://github.com/realm/realm-cocoa/issues/1186