質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

6905閲覧

RealmSwiftでリレーションのあるデータを削除するとクラッシュしてしまう

Natsu.mikan

総合スコア6

Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/04/08 15:18

編集2020/04/09 03:46

RealmSwiftを使ってアプリを作成しています。

リレーションのあるデータを削除する際に、下記の実装だとクラッシュしてしまいました。
エラーは下記です。

Thread 1: Exception: "The RLMArray has been invalidated or the object containing it has been deleted."

UnderlayerItemのみの削除であれば削除できました。
どうすれば、クラッシュせずに削除できるでしょうか?

swift

1struct ListView: View { 2 @ObservedObject private var fetcher = Fetcher() 3 @State private var title = "" 4 5 var body: some View { 6 NavigationView { 7 VStack { 8 TextField("タイトルを入力", text: $title) { 9 let item = Item() 10 item.title = self.title 11 let realm = try! Realm() 12 try! realm.write { 13 realm.add(item) 14 } 15 self.title = "" 16 } 17 18 ForEach(self.fetcher.items) { (item: Item) in 19 NavigationLink(destination: DetailView(item: item, id: item.id)) { 20 Text(item.title) 21 } 22 } 23 } 24 } 25 } 26}

swift

1struct DetailView: View { 2 var item: Item 3 var id: String 4 @State private var title = "" 5 @ObservedObject private var fetcher = Fetcher() 6 @Environment(.presentationMode) private var presentationMode: Binding<PresentationMode> 7 8 var body: some View { 9 VStack { 10 TextField("タイトルを入力", text: $title) { 11 let realm = try! Realm() 12 13 if let item = realm.objects(Item.self).filter("id == '(self.id)'").first { 14 try! realm.write() { 15 let underlayerItem = UnderlayerItem() 16 underlayerItem.title = self.title 17 item.underlayerItems.append(underlayerItem) 18 } 19 } 20 self.title = "" 21 } 22 23 ForEach(self.item.underlayerItems) { (underlayerItems: UnderlayerItem) in 24 Text(underlayerItems.title) 25 } 26 27 Button(action: { 28 self.presentationMode.wrappedValue.dismiss() 29 self.fetcher.delete(id: self.id) 30 }) { 31 Text("Delete") 32 } 33 } 34 } 35} 36

swift

1class Fetcher: ObservableObject { 2 var realm = try! Realm() 3 var objectWillChange: ObservableObjectPublisher = .init() 4 private(set) var items: Results<Item> 5 private var notificationTokens: [NotificationToken] = [] 6 7 init() { 8 items = realm.objects(Item.self) 9 10 notificationTokens.append(items.observe { _ in 11 self.objectWillChange.send() 12 }) 13 } 14 15 func delete(id: String) { 16 guard let item = realm.objects(Item.self).filter("id == '(id)'").first else { return } 17 try! realm.write() { 18 realm.delete(item.underlayerItems) 19 realm.delete(item) 20 } 21 } 22}

Swift

1 2class Item: Object, Identifiable { 3 @objc dynamic var id = NSUUID().uuidString 4 @objc dynamic var title = "" 5 @objc dynamic var createdAt = NSDate() 6 7 let underlayerItems: List<UnderlayerItem> = List<UnderlayerItem>() 8 9 override static func primaryKey() -> String? { 10 return "id" 11 } 12} 13 14class UnderlayerItem: Object, Identifiable { 15 @objc dynamic var id = NSUUID().uuidString 16 @objc dynamic var title = "" 17 @objc dynamic var createdAt = NSDate() 18 19 override static func primaryKey() -> String? { 20 return "id" 21 } 22}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Natsu.mikan

2020/04/09 01:34

データの追加や更新はできています。 また、クラッシュはしますが、削除もできています。
dsuzuki

2020/04/10 00:37

deleteの実行順を逆にしたらどうなりますか。
Natsu.mikan

2020/04/10 04:14

ありがとうございます。 実行順を逆にしてみましたが、同様にクラッシュしました。
guest

回答1

0

ベストアンサー

Deleteボタンを押して、DetailViewのitemをRealmから削除した後、

swift

1ForEach(self.item.underlayerItems) { (underlayerItems: UnderlayerItem) in 2 Text(underlayerItems.title) 3}

で、 self.itemに参照しているためエラーが発生しています。

上記のコードを

swift

1if !item.isInvalidated { 2 ForEach(self.item.underlayerItems) { (underlayerItems: UnderlayerItem) in 3 Text(underlayerItems.title) 4 } 5}

のようにして、itemが有効か判定してからアクセスすればエラーは解消されると思います。

投稿2020/04/10 14:39

TakeOne

総合スコア6299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問