Insert data with a one-to-one relationship without creating duplicates in SwiftData

52 Views Asked by At

I'm trying to insert a watchlist row with a show linked to it. But when the show exists, instead of updating it, it inserts a duplicate while it shouldn't be possible due to the @Attribute(.unique), causing the app to crash.

When I do modelContext.insert(show) directly, it correctly upserts it. But I can't manage to both link a show to a watchlist row and to not duplicate it.

Here's the code, thanks for the help

let showRow = ShowsRowLocal(id: viewModel.show.databaseId)
let watchlistRow = WatchlistRowLocal(show: showRow)
modelContext.insert(watchlistRow)
@Model
final class WatchlistRowLocal {
    var show: ShowsRowLocal

    init(show: ShowsRowLocal) {
        self.show = show
    }
}
@Model
final class ShowsRowLocal {
    @Attribute(.unique)
    var id: String

    @Relationship(deleteRule: .cascade, inverse: \WatchlistRowLocal.show)
    var watchlistRow: WatchlistRowLocal?

    init(id: String) {
        self.id = id
    }
}
1

There are 1 best solutions below

0
Emrecan Öztürk On BEST ANSWER

To ensure that you're not creating duplicates when inserting a WatchlistRowLocal with a linked ShowsRowLocal, you need to handle the relationship properly in SwiftData. Here's how you can achieve this:

// Check if the show already exists in the database
let existingShow = try modelContext.fetch(ShowsRowLocal.self, matching: \.$id == viewModel.show.databaseId).first

// Create or fetch the show
let showRow: ShowsRowLocal
if let existingShow = existingShow {
    // Show already exists, use it
    showRow = existingShow
} else {
    // Show doesn't exist, create a new one
    showRow = ShowsRowLocal(id: viewModel.show.databaseId)
    modelContext.insert(showRow)
}

// Create the watchlist row and link it to the show
let watchlistRow = WatchlistRowLocal(show: showRow)
modelContext.insert(watchlistRow)