SwiftData One To Many

I'm working through the Develop In Swift tutorial at page [https://developer.apple.com/tutorials/develop-in-swift/navigation-editing-and-relationships-conclusion)]

The tutorial has a one to many relationship between Friend and Movie (each friend can have at most one favorite movie and each movie can be the favorite for zero or more friends).

An exercise left to the student is to use an .onDelete on the movie detail page to delete that movie as favorite. I modified the Form

        Form {
            TextField("Movie title", text: $movie.title)
            DatePicker("Release date", selection: $movie.releaseDate, displayedComponents: .date)
            if !movie.favoritedBy.isEmpty {
                Section("Favorited by") {
                    ForEach(sortedFriends) { friend in
                        Text(friend.name)
                    }
                    .onDelete(perform: deleteFavorites(indexes:))
                }
            }
        }

by adding the .onDelete clause

I added

    private func deleteFavorites(indexes: IndexSet) {
        for index in indexes {
            context.delete(movie.favoritedBy[index])
        }
    }

to the view.

This does delete the favorite movie, but it also deletes the friend. My assumption is that the selected friend should then have no favorite movie rather than being deleted

There is an if in the Form that doesn't display the FAVORITED BY section if no friend has that movie as a favorite, but if I delete all the friends who had this movie as a favorite, the section remains (but is empty), until I exit the MovieDetail view and reload it

There is no answer for these exercises, so I could be doing it wrong.

EDIT: If I delete a movie using the app function to delete a movie, friends that have that movie as a favorite are not deleted and have their favorite movie set to None

Answered by DTS Engineer in 825007022

context.delete(movie.favoritedBy[index])

This does delete the favorite movie, but it also deletes the friend. My assumption is that the selected friend should then have no favorite movie rather than being deleted

movie.favoritedBy[index] points to a Friend object, and so the above code deletes the friend, doesn't?

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Accepted Answer

context.delete(movie.favoritedBy[index])

This does delete the favorite movie, but it also deletes the friend. My assumption is that the selected friend should then have no favorite movie rather than being deleted

movie.favoritedBy[index] points to a Friend object, and so the above code deletes the friend, doesn't?

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

But if you don’t like a movie anymore should a Friend or Movie really be deleted then, isn’t it the relationship that should be deleted/removed? Think about it…

Thanks for the reply.

The issue was my understanding of how relationships work in SwiftData. I thought I was deleting the relationship. Here's my corrected deleteFavorites method.

    private func deleteFavorites(indexes: IndexSet) {
        for index in indexes {
            let friend = movie.favoritedBy[index]
            friend.favoriteMovie = nil
        }
        do {
            try context.save()
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }

I had to add the context.save to get the view to update when no friends favorited a movie.

SwiftData One To Many
 
 
Q