SwiftData nested custom model CRASH

@Model class AModel {
    @Attribute(.unique) var id:String
    var date:Date
    var b:[BModel]
    init() {
        self.id = UUID().uuidString
        self.date = Date()
        self.b = []
    }
}
@Model class BModel {
    @Attribute(.unique) var id:String
    var date:Date
    init() {
        self.id = UUID().uuidString
        self.date = Date()
    }
}

struct MainView: View {
    @Environment(\.modelContext) private var db
    @State private var a:AModel = AModel()
    
    var body: some View {
        VStack {

        }
        .onAppear {
            a.b.append(BModel())
            print(a.b)
        }
    }
}

// CRASH :
@Model class AModel {
    @Attribute(.unique) var id:String
    var date:Date
    var b:[BModel]
/**
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
{
    get {
        _$observationRegistrar.access(self, keyPath: \.b)
        return self.getValue(for: \.b)
    }

    set {
        _$observationRegistrar.withMutation(of: self, keyPath: \.b) {
          self.setValue(for: \.b, to: newValue)
        }
    }
}
*/
    init() {
        self.id = UUID().uuidString
        self.date = Date()
        self.b = []
    }
}
@Model class BModel {
    @Attribute(.unique) var id:String
    var date:Date
    init() {
        self.id = UUID().uuidString
        self.date = Date()
    }
}


Post not yet marked as solved Up vote post of mandriao84 Down vote post of mandriao84
1.3k views

Replies

I'm having this exact issue and am stumped. Hoping someone else chimes in.

  • I am also having the same issues.

Add a Comment

Same issue

Ok so two issues I can see here, forgive me if I'm wrong but I need to rush this answer

First up you're not using Relationships

@Model class AModel {
    @Attribute(.unique) var id:String
    var date:Date
    @Relationship(inverse: \BModel.aModel)
    var b:[BModel]
}

 
@Model class BModel {
    @Attribute(.unique) var id:String
    var date:Date
    var aModel: AModel?

    init() {
        self.id = UUID().uuidString
        self.date = Date()
    }
}

Secondly, and this is something that only started happening to me in the last two betas. I found I need to insert the bModel before appending it to a property in aModel. This may not be the issue, as usually this only affects me when passing a model through in an initialiser, but worth a shot

.onAppear {
    let model = BModel()
    modelContext.insert(model)
    a.b.append(model)
    print(a.b)
 }

Again, apologies if I misunderstood the question, I'm in a bit of a rush here. Let me know if I can help more

  • Not sure about the @mandriao84 , but this solution didn't work for me. I'm using the same classes as codable to handle API response. So BModel is only initialised inside AModel init(from decoder: Decoder). So your solution inside onAppear doesn't work in my case.

Add a Comment