Fixes crashes when loading Game or SaveState that had been overwritten by a duplicate entry
When Core Data detects a duplicate entry, it deletes the previous entry. This caused Delta to delete the associated ROM and Save State files. Now, there is a check in prepareForDeletion to make sure the object being deleted is not simply being replaced by a newer entry during a merge.
This commit is contained in:
parent
9648aec3b5
commit
5c6c66c9a1
@ -30,6 +30,12 @@ extension Game
|
|||||||
{
|
{
|
||||||
super.prepareForDeletion()
|
super.prepareForDeletion()
|
||||||
|
|
||||||
|
guard let managedObjectContext = self.managedObjectContext else { return }
|
||||||
|
|
||||||
|
// If a game with the same identifier is also currently being inserted, Core Data is more than likely resolving a conflict by deleting the previous instance
|
||||||
|
// In this case, we make sure we DON'T delete the game file + misc other Core Data relationships, or else we'll just lose all that data
|
||||||
|
guard !managedObjectContext.insertedObjects.contains(where: { ($0 as? Game)?.identifier == self.identifier }) else { return }
|
||||||
|
|
||||||
guard FileManager.default.fileExists(atPath: self.fileURL.path) else { return }
|
guard FileManager.default.fileExists(atPath: self.fileURL.path) else { return }
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -41,25 +47,22 @@ extension Game
|
|||||||
print(error)
|
print(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let managedObjectContext = self.managedObjectContext
|
for collection in self.gameCollections where collection.games.count == 1
|
||||||
{
|
{
|
||||||
for collection in self.gameCollections where collection.games.count == 1
|
// Once this game is deleted, collection will have 0 games, so we should delete it
|
||||||
{
|
managedObjectContext.delete(collection)
|
||||||
// Once this game is deleted, collection will have 0 games, so we should delete it
|
}
|
||||||
managedObjectContext.delete(collection)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manually cascade deletion since SaveState.fileURL references Game, and so we need to ensure we delete SaveState's before Game
|
// Manually cascade deletion since SaveState.fileURL references Game, and so we need to ensure we delete SaveState's before Game
|
||||||
// Otherwise, we crash when accessing SaveState.game since it is nil
|
// Otherwise, we crash when accessing SaveState.game since it is nil
|
||||||
for saveState in self.saveStates
|
for saveState in self.saveStates
|
||||||
{
|
{
|
||||||
managedObjectContext.delete(saveState)
|
managedObjectContext.delete(saveState)
|
||||||
}
|
}
|
||||||
|
|
||||||
if managedObjectContext.hasChanges
|
if managedObjectContext.hasChanges
|
||||||
{
|
{
|
||||||
managedObjectContext.saveWithErrorLogging()
|
managedObjectContext.saveWithErrorLogging()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,12 @@ public class SaveState: _SaveState, SaveStateProtocol
|
|||||||
// In rare cases, game may actually be nil if game is corrupted, so we ensure it is non-nil first
|
// In rare cases, game may actually be nil if game is corrupted, so we ensure it is non-nil first
|
||||||
guard self.game != nil else { return }
|
guard self.game != nil else { return }
|
||||||
|
|
||||||
|
guard let managedObjectContext = self.managedObjectContext else { return }
|
||||||
|
|
||||||
|
// If a save state with the same identifier is also currently being inserted, Core Data is more than likely resolving a conflict by deleting the previous instance
|
||||||
|
// In this case, we make sure we DON'T delete the save state file + misc other Core Data relationships, or else we'll just lose all that data
|
||||||
|
guard !managedObjectContext.insertedObjects.contains(where: { ($0 as? SaveState)?.identifier == self.identifier }) else { return }
|
||||||
|
|
||||||
guard FileManager.default.fileExists(atPath: self.fileURL.path) else { return }
|
guard FileManager.default.fileExists(atPath: self.fileURL.path) else { return }
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user