UPDATE: Eine verbesserte Antwort, basierend auf James Huddlestons Ideen in der folgenden Diskussion.
- (BOOL)hasManagedObjectBeenDeleted:(NSManagedObject *)managedObject {
NSParameterAssert(managedObject);
NSManagedObjectContext *moc = [self managedObjectContext];
if ([moc respondsToSelector:@selector(existingObjectWithID:error:)])
{
NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *managedObjectClone = [moc existingObjectWithID:objectID error:NULL];
if (!managedObjectClone)
return YES;
else
return NO;
}
else if ([moc respondsToSelector:@selector(countForFetchRequest:error:)])
{
if (![managedObject managedObjectContext])
return YES;
NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *managedObjectClone = [moc objectWithID:objectID];
NSEntityDescription *entityDescription = [managedObjectClone entity];
NSDictionary *propertiesByName = [entityDescription propertiesByName];
NSArray *propertyNames = [propertiesByName allKeys];
NSAssert1([propertyNames count] != 0, @"Method cannot detect if |managedObject| has been deleted because it has zero Properties defined: %@", managedObject);
@try
{
(void)[managedObjectClone valueForKey:[propertyNames objectAtIndex:0]];
return NO;
}
@catch (NSException *exception)
{
if ([[exception name] isEqualToString:NSObjectInaccessibleException])
return YES;
else
[exception raise];
}
}
else
{
NSAssert(0, @"Unsupported version of Mac OS X detected.");
}
}
ALTE / VERRÜCKTE ANTWORT:
Ich habe eine etwas bessere Methode geschrieben. self
ist Ihre Core Data-Klasse / Controller.
- (BOOL)hasManagedObjectBeenDeleted:(NSManagedObject *)managedObject
{
if (![managedObject managedObjectContext])
return YES;
NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *managedObjectClone = [[self managedObjectContext] objectWithID:objectID];
NSEntityDescription *entityDescription = [managedObjectClone entity];
NSDictionary *propertiesByName = [entityDescription propertiesByName];
NSArray *propertyNames = [propertiesByName allKeys];
@try
{
for (id propertyName in propertyNames)
(void)[managedObjectClone valueForKey:propertyName];
return NO;
}
@catch (NSException *exception)
{
if ([[exception name] isEqualToString:NSObjectInaccessibleException])
return YES;
else
[exception raise];
}
}
Wie James Huddleston in seiner Antwort erwähnte, ist die Überprüfung, ob die -managedObjectContext
Rückgabe von NSManagedObject nil
eine "ziemlich gute" Methode ist, um festzustellen, ob ein zwischengespeichertes / veraltetes NSManagedObject aus dem persistenten Speicher gelöscht wurde, aber nicht immer korrekt, wie Apple in seinen Dokumenten feststellt:
Diese Methode kann null zurückgeben, wenn der Empfänger aus seinem Kontext gelöscht wurde.
Wann wird es nicht null zurückgeben? Wenn Sie ein anderes NSManagedObject mit den gelöschten NSManagedObjects erwerben, gehen Sie -objectID
wie folgt vor :
CoreData *coreData = ...;
NSManagedObject *apple = [coreData addManagedObject:@"Apple"];
[apple setValue:@"Mcintosh" forKey:@"name"];
[coreData saveMOCToPersistentStore];
NSManagedObjectContext *moc = [apple managedObjectContext];
if (!moc)
NSLog(@"2 - Deleted.");
else
NSLog(@"2 - Not deleted.");
[[coreData managedObjectContext] deleteObject:apple];
moc = [apple managedObjectContext];
if (!moc)
NSLog(@"3 - Deleted.");
else
NSLog(@"3 - Not deleted.");
[coreData saveMOCToPersistentStore];
moc = [apple managedObjectContext];
if (!moc)
NSLog(@"4 - Deleted.");
else
NSLog(@"4 - Not deleted.");
NSManagedObjectID *deletedAppleObjectID = [apple objectID];
NSManagedObject *appleClone = [[coreData managedObjectContext] objectWithID:deletedAppleObjectID];
moc = [appleClone managedObjectContext];
if (!moc)
NSLog(@"5 - Deleted.");
else
NSLog(@"5 - Not deleted.");
BOOL deleted = [coreData hasManagedObjectBeenDeleted:appleClone];
if (deleted)
NSLog(@"6 - Deleted.");
else
NSLog(@"6 - Not deleted.");
Hier ist der Ausdruck:
2 - Not deleted.
3 - Not deleted.
4 - Deleted.
5 - Not deleted.
6 - Deleted.
Wie Sie sehen, -managedObjectContext
wird nicht immer nil zurückgegeben, wenn ein NSManagedObject aus dem Persistent Store gelöscht wurde.
isInserted
die ein BOOL auf NSManagedObject zurückgibt, was meines Wissens dasselbe bedeutet. Es ist wahrscheinlich etwas sauberer, es für diesen Fall zu verwenden.