Lorsque je supprime un NSMangedObject
de la base de données, qu'advient-il des variables locales qui lui ont été affectées?Qu'arrive-t-il aux variables locales qui stockent des références à des fichiers NSManagedObjects supprimés?
Par exemple, j'ai simple NSManagedObject:
class MyManagedObject: NSManagedObject {
@NSManaged var name: String
}
Et puis dans mon ViewController, je le tire hors de la base de données, et l'affecter localement:
class ViewController: UIViewController {
var myManagedObject: MyManagedObject!
}
Je le supprimer de la base de données.
Si imprimer le nom de l'objet que je reçois le texte suivant dans la console
print("myManagedObject.name = \(myManagedObject.name)")
//prints: "myManagedObject.name = "
Comme si l'objet n'est pas là? Mais si je transforme la variable en option et la vérifie pour rien, on me dit que ce n'est pas nul.
Je ne sais pas comment concilier cela dans mon esprit. Il semble y avoir quelque chose qui pointe vers la variable locale, mais ses propriétés ont disparu.
Si j'ai de nombreux objets IU disparates qui dépendent de cet objet pour ses propriétés, je ne peux pas supposer qu'il existe une copie profonde locale de celui-ci en mémoire?
est ici code plus complet:
En viewDidLoad je crée le nouvel objet, sauvegarder le contexte, chercher l'objet, puis l'affecter localement.
class ViewController: UIViewController {
var myManagedObject: MyManagedObject!
override func viewDidLoad() {
super.viewDidLoad()
//1 Create the new object
let newObject = NSEntityDescription.insertNewObject(forEntityName: "MyManagedObject", into: coreDataManager.mainContext) as! MyManagedObject
newObject.name = "My First Managed Object"
//2 Save it into the context
do {
try coreDataManager.mainContext.save()
} catch {
//handle error
}
//3 Fetch it from the database
let request = NSFetchRequest<MyManagedObject>(entityName: "MyManagedObject")
do {
let saved = try coreDataManager.mainContext.fetch(request)
//4 Store it in a local variable
self.myManagedObject = saved.first
} catch {
//handle errors
}
}
}
À ce stade, si j'imprime la propriété variable locale de name
, je reçois la réponse correcte:
print("The object's name is: \(myManagedObject.name)")
//prints: The object's name is: My First Managed Object
Alors, maintenant, je le supprimer de la base de données:
if let storedObject = myManagedObject {
coreDataManager.mainContext.delete(storedObject)
do {
try coreDataManager.mainContext.save()
} catch {
//handle error
}
}
Mais maintenant, quand j'imprime je reçois la sortie la plus étrange:
print("myManagedObject.name = \(myManagedObject.name)")
//prints: "myManagedObject.name = "
Ce n'est vraiment pas la façon dont je m'attends à ce que la mémoire fonctionne. Si je crée une instance d'une classe Foo
, puis passez cette instance à différents objets, c'est la même instance. Il ne disparaît qu'une fois que personne ne l'indique.
Dans ce cas --- quelle est la variable, myManagedObject
? Ce n'est pas nil
. Et quelle est la chaîne, name
? Est-ce une chaîne vide? Ou est-ce un autre méta-type bizarre?
Afficher le code où vous "l'attribuez" localement. var myManagedObject: MyManagedObject! va juste "faire" une nouvelle variable de type MyManagedObject – Retterdesdialogs
En raison de la mise à jour de votre question: Après avoir supprimé l'objet géré, vous l'avez marqué comme supprimé et après l'avoir sauvegardé, vous le supprimez de la base de données (pas en mémoire). Sur l'objet géré, vous devriez vérifier la propriété isDeleted ou même la propriété "fault". L'objet persiste dans la mémoire comme vous l'avez prévu mais son comportement est dans votre cas imprévisible.Tout peut arriver en fonction des changements dans le cadre et la chaîne vide semble être une bonne solution pour que cela fonctionne encore. C'est votre travail de ne pas utiliser cet objet après qu'il a été supprimé. –
Mais le trou de lapin va plus loin. Si vous utilisez plusieurs contextes et que vous supprimez l'objet dans un contexte, il existera toujours dans l'autre. Mais une fois que vous essaierez d'appliquer des changements dans le second contexte, un conflit sera signalé, que vous devrez résoudre. Ainsi, en mémoire, vous aurez une instance par contexte et ces instances seront conservées en mémoire jusqu'à ce que les règles d'ARC décident de la libérer. Mais ses propriétés peuvent changer à tout moment. Ergo l'objet existe toujours mais ses propriétés sont inaccessibles. Par tous les droits, il devrait tomber en panne, mais il semble que l'exception a été traitée pour vous. –