ios – Crashed while using @EnvironmentObject with Realm


I constructed a minimization program to simplify things:

Model:

import RealmSwift

class Space: Object, Identifiable {
    @Persisted(primaryKey: true) var id: ObjectId
    @Persisted var name: String = ""
    
    convenience init(name: String) {
        self.init()
        self.name = name
    }
}

ViewModel:

import Foundation
import RealmSwift

class SpaceStore: ObservableObject {
    @Published var spaces: Results<Space>?
    
    private static let realm = try! Realm()
    private var realmToken: NotificationToken?
    
    init() {
        let results = SpaceStore.realm.objects(Space.self)
        realmToken = results.observe { _ in
            self.spaces = results
        }
    }
    
    func add(by name: String) {
        let space = Space(name: name)
        try! SpaceStore.realm.write {
            SpaceStore.realm.add(space)
        }
    }
    
    func delete(_ space: Space) {
        try! SpaceStore.realm.write {
            SpaceStore.realm.delete(space)
        }
    }
}

ContentView:

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var store: SpaceStore
    
    var body: some View {
        Button("Add") {
            store.add(by: "qwerty")
        }
        Divider()
        if let spaces = store.spaces {
            ForEach(spaces) { space in
                HStack {
                    Text(space.name)
                    Button("Delete") {
                        store.delete(space)
                    }
                }
            }
            Divider()
            if let spaceItem = spaces.first {
                ItemView(space: spaceItem)
            }
            Divider()
            ForEach(spaces) { space in
                // RowView(space: space)
            }
        }
        
    }
}

#Preview {
    ContentView()
        .environmentObject(SpaceStore())
}

ItemView:

import SwiftUI

struct ItemView: View {
    let space: Space
    @EnvironmentObject var store: SpaceStore
    
    var body: some View {
        HStack {
            Text(space.name)
            Button("Delete") {
                store.delete(space)
            }
        }
    }
}

#Preview {
    ItemView(space: Space(name: "e"))
        .environmentObject(SpaceStore())
}

The entrance:

import SwiftUI

@main
struct ForTestApp: App {
    @StateObject private var store = SpaceStore()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(store)
        }
    }
}

And the RowView is almost the same as ItemView except name so I omitted it.


Here is the weird things during debugging:

  1. delete inside the ContentView, it’s ok
  2. delete in the ItemView for just one item, it’s ok
  3. delete in the RowView (inside ForEach), boooooom~

P.S.:

  1. While I import the RowView, delete action of 1&2 turn to be crashed too.
  2. Data was successfully deleted even though crashed after that. So I suppose that the crash was happened during the rerendering.

Then I replaced the @EnvironmentObject var store: SpaceStore with let store: SpaceStore in RowView and everything seems to be working well.

At last, I tried to wrap the delete action in a confirmationDialog like this:

.confirmationDialog("", isPresented: $ifShowSheetOfSettings) {
   Button("delete") {
      store.delete(space)
   }
}

It crashed again.

I hope someone can help me to figure out and point out the cause of the crash which is the most important.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img