Search code examples
swiftcore-datansmanagedobject

Do you need to save ManagedObjectContext in order for a Nullify delete rule to affect destination entity?


I'm saving chessGames and chessPlayers to a DB using core data. -Each chessGame has a to-one relationship to a white Player and black player (with a delete rule set to nullify). -Each player has to-many relationship to gamesAsWhite and to gamesAsBlack (with a delete rule set to deny).

When ever I delete a chessGame I also try to delete the players involved in that game, if the players are not involved in any other games. As shown in code below.

Code used to delete chess game and potentially players too:

context.perform {
                //deletes associated chessgameSnapShot
                context.delete(chessGameMO)
                CoreDataUtilities.save(context: context)
                //delete rule set to deny
                //player only deleted if it is not involved in any games
                whitePlayer.deleteIfNotInvolvedInAnyGames(inManagedObjectContext: context)
                blackPlayer.deleteIfNotInvolvedInAnyGames(inManagedObjectContext: context)
                CoreDataUtilities.save(context: context)
            }

Implementation of deleteIfNotInvolvedInAnyGames:

func deleteIfNotInvolvedInAnyGames(inManagedObjectContext context:NSManagedObjectContext){
        guard let gamesAsBlack =  self.gamesAsBlack as? Set<ChessGameMO>,
            let gamesAsWhite =  self.gamesAsWhite as? Set<ChessGameMO> else {return}
        let gamesInvolvedIn = gamesAsWhite.union(gamesAsBlack)
        if gamesInvolvedIn.isEmpty {
            context.delete(self)
        }
    }

The code only works if I save the context after I delete the chessGame. If I remove the first CoreDataUtilities.save(context: context) then the whitePlayer (and the blackPlayer) never get deleted in the deleteIfNotInvolvedInAnyGames because the relationship to chessGameMO doesn't seem to have nullified yet.

Is this normal behaviour? Shouldn't the relationships between the NSManagedObjects (in memory) be updated before I save the context?


Solution

  • You initial understanding is correct - validation only happens on save. So if you deleted the game and the player and then saved it should work assuming that all changes are valid. BUT the relationships are not updated until save. The relationship is still there, it is just pointing to a deleted object (object.isDeleted). So your code in deleteIfNotInvolvedInAnyGames has to filter out all deleted objects and then see if the set is empty.