1

Let's say in SwiftUI / SwiftData, we have two models:

@Model
final class Thing1 {
    
    private var things:[Thing2]
    
    func deleteThing(thing: Thing2) {
        things.removeAll(where: {$0.persistentModelID == thing.persistentModelID})
    }
    
    init(things: [Thing2]) {
        self.things = things
    }
    
}

@Model
final class Thing2 {

    init() {}
    
}

The problem here is that, when we use the delete function, as we know, it's not really deleted in SwiftData.

Normally we would use the modelContext to do that, but... for lengthy reasons (see this question), I'm experimenting with not doing it that way. I'm also assuming that we can't get a working reference to the modelContext from inside Thing1.

I know that it is possible to implicitly delete items without using modelContext. For example using @Relationship(deleteRule: .cascade), but this is only for single items, not arrays.

Is there some way to do this?

1
  • Not available in SwiftData built-in, CoreData lets you do it but not SwiftData. Maybe in June. Commented Jan 21, 2024 at 1:13

1 Answer 1

2

Your assumption that you can't get access to a ModelContext is wrong, look at the documentation for PersistentModel and it clearly has such a property.

This property is optional since it is not set until you have inserted the model object into the context but once that is done it has a reference to its model context.

So given that we do can create such a delete function as you want.

func deleteThing(thing: Thing2) throws {    
    guard let modelContext = self.modelContext, thing.thing == self else { return }
    modelContext.delete(thing)
    try modelContext.save()
}

First we use a guard statement to check that self exists in a model context and that the given Thing2 is related to Thing1 object.

Then we delete the given Thing2 but this will only mark it as deleted and it will still exists in the things array so to remove it completely we must also save the context.

For view related code and with autosaving enabled for the context saving directly might not be so important since it is done asynchronously almost directly after but if you have code running synchronously directly after the function it's important to be aware of the state of both instances so either call save or take precaution checking the isDeleted property.

Of course, as mentioned in the question, if the delete rules for the @Relationship worked properly we probably wouldn't need this at all.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.