🔬
【SwiftData】DeleteRule 観測隊 (.cascade .nullify .deny .noAction)
1:1
片方向 A->B
サンプルコード
@Model
final class TestA {
var name: String
@Relationship(deleteRule: .cascade) var testB: TestB?
//以下略
@Model
final class TestB {
var name: String
//以下略
A内のBにはBインスタンスを登録する。
A内のBの宣言 | B内のAの宣言 | Aを削除したとき | Bを削除したとき |
---|---|---|---|
.cascade | - | A消える B消える 問題なし |
A消えない B消える A内のBにアクセスするとEXC_BREAKPOINT |
.nullify | - | A消える B消えない 問題なし |
A消えない B消える A内のBにアクセスするとEXC_BREAKPOINT |
.deny | - | A消える B消えない エラー大量、実行は継続 |
A消えない B消える A内のBにアクセスするとEXC_BREAKPOINT |
.noAction | - | A消える B消えない 問題なし |
A消えない B消える A内のBにアクセスするとEXC_BREAKPOINT |
双方向 C<->D
サンプルコード
@Model
final class TestC {
var name: String
@Relationship(deleteRule: .cascade) var testD: TestD?
//以下略
@Model
final class TestD {
var name: String
@Relationship(deleteRule: .cascade) var testC: TestC?
//以下略
C内のDにはDインスタンスを登録する。
C内のDの宣言 | D内のCの宣言 | Cを削除したとき | Dを削除したとき |
---|---|---|---|
.cascade | .cascade | 両方消える 問題なし |
両方消える 問題なし |
.cascade | .nullify | 両方消える 問題なし |
C消えない D消える 問題なし |
.cascade | .deny | 両方消える 問題なし |
EXC_BAD_ACCESS |
.cascade | .noAction | 両方消える 問題なし |
EXC_BAD_ACCESS |
.nullify | .nullify | C消える D消えない 問題なし |
C消えない D消える 問題なし |
.nullify | .deny | C消える D消えない 問題なし |
EXC_BAD_ACCESS |
.nullify | .noAction | C消える D消えない 問題なし |
EXC_BAD_ACCESS |
.deny | .deny | EXC_BAD_ACCESS | EXC_BAD_ACCESS |
.deny | .noAction | EXC_BAD_ACCESS | EXC_BAD_ACCESS |
.noAction | .noAction | EXC_BAD_ACCESS | EXC_BAD_ACCESS |
1:N
片方向 E->F
サンプルコード
@Model
final class TestE {
var name: String
@Relationship(deleteRule: .noAction) var testF: [TestF] = []
//以下略
@Model
final class TestF {
var name: String
//以下略
E内のFに2つ入れる。
E内のFの宣言 | F内のEの宣言 | Eを削除したとき | Fを削除したとき |
---|---|---|---|
.cascade | - | E消える F消える 問題なし |
F消える EのFにアクセスするとEXC_BREAKPOINT |
.nullify | - | E消える F消えない 問題なし |
F消える EのFにアクセスするとEXC_BREAKPOINT |
.deny | - | E消える F消えない エラー大量 |
F消える EのFにアクセスするとEXC_BREAKPOINT |
.noAction | - | E消える F消えない 問題なし |
F消える EのFにアクセスするとEXC_BREAKPOINT |
片方向 G<-H
サンプルコード
@Model
final class TestG {
var name: String
//以下略
@Model
final class TestH {
var name: String
@Relationship(deleteRule: .cascade) var testG: TestG?
//以下略
複数のHから同じGに接続。
G内のHの宣言 | H内のGの宣言 | Gを削除したとき | Hを削除したとき |
---|---|---|---|
- | .cascade | G消える HのGにアクセスするとEXC_BREAKPOINT |
G消える H消える もうひとつのHのGにアクセスするとEXC_BREAKPOINT |
- | .nullify | G消える HのGにアクセスするとEXC_BREAKPOINT |
G消えない H消える 問題なし |
- | .deny | G消える HのGにアクセスするとEXC_BREAKPOINT |
G消えない H消える エラー大量、実行は継続 |
- | .noAction | G消える HのGにアクセスするとEXC_BREAKPOINT |
G消えない H消える 問題なし |
双方向 I<->J
サンプルコード
@Model
final class TestI {
var name: String
@Relationship(deleteRule: .noAction) var testJ: [TestJ] = []
//以下略
@Model
final class TestJ {
var name: String
@Relationship(deleteRule: .noAction) var testI: TestI?
//以下略
複数のJから同じIに接続。
I内のJの宣言 | J内のIの宣言 | Iを削除したとき | Jを削除したとき |
---|---|---|---|
.cascade | .cascade | I消える J全て消える 問題なし |
J消える I消える Iに関連する他のJ消える 問題なし |
.cascade | .nullify | I消える J全て消える 問題なし |
消したJだけ消える I消えない Iに関連する他のJ消えない 問題なし |
.cascade | .deny | I消える J全て消える 問題なし |
消したJだけ消える I消えない Iに関連する他のJ消えない エラー大量、実行は継続 |
.cascade | .noAction | I消える J全て消える 問題なし |
消したJだけ消える I消えない Iに関連する他のJ消えない IのJにアクセスするとEXC_BREAKPOINT |
.nullify | .nullify | I消える J消えない 問題なし |
消したJだけ消える I消えない Iに関連する他のJ消えない 問題なし |
.nullify | .deny | I消える J消えない 問題なし |
消したJだけ消える I消えない Iに関連する他のJ消えない エラー大量、実行は継続 |
.nullify | .noAction | I消える J消えない 問題なし |
消したJだけ消える I消えない Iに関連する他のJ消えない IのJにアクセスするとEXC_BREAKPOINT |
.deny | .deny | I消える J消えない エラー大量、実行は継続 |
消したJだけ消える I消えない Iに関連する他のJ消えない エラー大量、実行は継続 |
.deny | .noAction | I消える J消えない エラー大量、実行は継続 |
消したJだけ消える I消えない Iに関連する他のJ消えない IのJにアクセスするとEXC_BREAKPOINT |
.noAction | .noAction | I消える J消えない JのIにアクセスするとEXC_BREAKPOINT |
消したJだけ消える I消えない Iに関連する他のJ消えない IのJにアクセスするとEXC_BREAKPOINT |
N:N
片方向参照 K->L
サンプルコード
@Model
final class TestK {
var name: String
@Relationship(deleteRule: .cascade) var testL: [TestL] = []
//以下略
@Model
final class TestL {
var name: String
//以下略
K内のLに2つ入れる。
K内のLの宣言 | L内のKの宣言 | Kを削除したとき | Lを削除したとき |
---|---|---|---|
.cascade | - | K消える L消える 問題なし |
L消える KのLにアクセスするとEXC_BREAKPOINT |
.nullify | - | K消える L消えない 問題なし |
L消える KのLにアクセスするとEXC_BREAKPOINT |
.deny | - | K消える L消えない エラー大量 |
L消える KのLにアクセスするとEXC_BREAKPOINT |
.noAction | - | K消える L消えない 問題なし |
L消える KのLにアクセスするとEXC_BREAKPOINT |
双方向参照 inverse設定なし O<->P
サンプルコード
@Model
final class TestO {
var name: String
@Relationship(deleteRule: .cascade) var testP: [TestP] = []
//以下略
@Model
final class TestP {
var name: String
@Relationship(deleteRule: .cascade) var testO: [TestO] = []
//以下略
2つのOと2つのPがすべて組み合わさっている。
O内のPの宣言 | P内のOの宣言 | Oを削除したとき | Pを削除したとき |
---|---|---|---|
.cascade | .cascade | 連鎖すべて消える | 連鎖すべて消える |
.cascade | .nullify | 消したO消える 消したOと繋がっているPは消える 消えたPと繋がっている他のOは消えない 残ったOのPにアクセスするとEXC_BREAKPOINT |
消したP消える 消したPと繋がっているOは消えない Oの消えたPにアクセスするとEXC_BREAKPOINT |
.cascade | .deny | 消したO消える 消したOと繋がっているPは消える 消えたPと繋がっている他のOは消えない エラー大量、実行継続 |
消したP消える 消したPと繋がっているOは消えない エラー大量、実行継続 |
.cascade | .noAction | 消したO消える 消したOと繋がっているPは消える 消えたPと繋がっている他のOは消えない 残ったOのPにアクセスするとEXC_BREAKPOINT |
消したP消える 消したPと繋がっているOは消えない Oの消したPにアクセスするとEXC_BREAKPOINT |
.nullify | .nullify | 消したO消える 消したOと繋がっているPは消えない Pの消したOにアクセスするとEXC_BREAKPOINT |
消したP消える 消したPと繋がっているOは消えない Oの消したPにアクセスするとEXC_BREAKPOINT |
.nullify | .deny | 消したO消える 消したOと繋がっているPは消えない Pの消したOにアクセスするとEXC_BREAKPOINT |
消したP消える 消したPと繋がっているOは消えない エラー大量、実行継続 |
.nullify | .noAction | 消したO消える 消したOと繋がっているPは消えない Pの消したOにアクセスするとEXC_BREAKPOINT |
消したP消える 消したPと繋がっているOは消えない Oの消したPにアクセスするとEXC_BREAKPOINT |
.deny | .deny | 消したO消える 消したOと繋がっているPは消えない エラー大量、実行継続 |
消したP消える 消したPと繋がっているOは消えない エラー大量、実行継続 |
.deny | .noAction | 消したO消える 消したOと繋がっているPは消えない エラー大量、実行継続 |
消したP消える 消したPと繋がっているOは消えない Oの消したPにアクセスするとEXC_BREAKPOINT |
.noAction | .noAction | 消したO消える 消したOと繋がっているPは消えない Pの消したOにアクセスするとEXC_BREAKPOINT |
消したP消える 消したPと繋がっているOは消えない Oの消したPにアクセスするとEXC_BREAKPOINT |
双方向参照 inverse設定付き Q<->R
サンプルコード
@Model
final class TestQ {
var name: String
@Relationship(deleteRule: .cascade, inverse: \TestR.testQ) var testR: [TestR] = []
//以下略
@Model
final class TestR {
var name: String
@Relationship(deleteRule: .cascade) var testQ: [TestQ] = []
//以下略
2つのQと2つのRがすべて組み合わさっている。
Q内のRの宣言 | R内のQの宣言 | Qを削除したとき | Rを削除したとき |
---|---|---|---|
.cascade | .cascade | 連鎖すべて消える | 連鎖すべて消える |
.cascade | .nullify | 消したQ消える 消したQと繋がっているRは消える 消えたRと繋がっている他のQは消えない 問題なし |
消したR消える 消したRと繋がっているQは消えない 問題なし |
.cascade | .deny | 消したQ消える 消したQと繋がっているRは消える 消えたRと繋がっている他のQは消えない エラー大量、実行継続 |
消したR消える 消したRと繋がっているQは消えない エラー大量、実行継続 |
.cascade | .noAction | 消したQ消える 消したQと繋がっているRは消える 消えたRと繋がっている他のQは消えない 残ったQのRにアクセスするとEXC_BREAKPOINT |
消したR消える 消したRと繋がっているQは消えない Qの消したRにアクセスするとEXC_BREAKPOINT |
.nullify | .cascade | 消したQ消える 消したQと繋がっているRは消えない 問題なし |
消したR消える 消したRと繋がっているQは消える 消えたQと繋がっている他のRは消えない 問題なし |
.nullify | .nullify | 消したQ消える 消したQと繋がっているRは消えない 問題なし |
消したR消える 消したRと繋がっているQは消えない 問題なし |
.nullify | .deny | 消したQ消える 消したQと繋がっているRは消えない 問題なし |
消したR消える 消したRと繋がっているQは消えない エラー大量、実行継続 |
.nullify | .noAction | 消したQ消える 消したQと繋がっているRは消えない 問題なし |
消したR消える 消したRと繋がっているQは消えない Qの消したRにアクセスするとEXC_BREAKPOINT |
.deny | .cascade | 消したQ消える 消したQと繋がっているRは消えない エラー大量、実行継続 |
消したR消える 消したRと繋がっているQは消える 消えたQと繋がっている他のRは消えない エラー大量、実行継続 |
.deny | .nullify | 消したQ消える 消したQと繋がっているRは消えない エラー大量、実行継続 |
消したR消える 消したRと繋がっているQは消えない 問題なし |
.deny | .deny | 消したQ消える 消したQと繋がっているRは消えない エラー大量、実行継続 |
消したR消える 消したRと繋がっているQは消えない エラー大量、実行継続 |
.deny | .noAction | 消したQ消える 消したQと繋がっているRは消えない エラー大量、実行継続 |
消したR消える 消したRと繋がっているQは消えない Qの消したRにアクセスするとEXC_BREAKPOINT |
.noAction | .cascade | 消したQ消える 消したQと繋がっているRは消えない Rの消したQにアクセスするとEXC_BREAKPOINT |
消したR消える 消したRと繋がっているQは消える 消えたQと繋がっている他のRは消えない 残ったRのQにアクセスするとEXC_BREAKPOINT |
.noAction | .nullify | 消したQ消える 消したQと繋がっているRは消えない Rの消したQにアクセスするとEXC_BREAKPOINT |
消したR消える 消したRと繋がっているQは消えない 問題なし |
.noAction | .deny | 消したQ消える 消したQと繋がっているRは消えない Rの消したQにアクセスするとEXC_BREAKPOINT |
消したR消える 消したRと繋がっているQは消えない エラー大量、実行継続 |
.noAction | .noAction | 消したQ消える 消したQと繋がっているRは消えない Rの消したQにアクセスするとEXC_BREAKPOINT |
消したR消える 消したRと繋がっているQは消えない Qの消したRにアクセスするとEXC_BREAKPOINT |
接続なしの状態について
それぞれのパターンで接続なし、つまり参照を表す変数が
- nil
- 配列が空
であれば、削除しても、削除したものだけが消えて、他に影響をあたえず問題ない。
まとめ、考察
denyが指定してあるものはUI上で消えてもデータは残っているかも
N対Nの両nullifyにするときはinverseの設定が必須
配列の要素を削除する時
ここまではインスタンスを丸ごと削除するときの挙動を見てきたが、N:1やN:Nのときは配列で他の要素を保持することもある。配列の要素を削除するときの挙動は
.nullify
は想定通りの挙動をするが、.cascade
は .nullify
の挙動をするようである。
他の記事
主に配列の要素を削除するときなど図入りで書きました。
Discussion