UPDATE: Eine verbesserte Antwort, basierend auf James Huddleston ‚s Ideen in der Diskussion unten.
- (BOOL)hasManagedObjectBeenDeleted:(NSManagedObject *)managedObject {
/*
Returns YES if |managedObject| has been deleted from the Persistent Store,
or NO if it has not.
NO will be returned for NSManagedObject's who have been marked for deletion
(e.g. their -isDeleted method returns YES), but have not yet been commited
to the Persistent Store. YES will be returned only after a deleted
NSManagedObject has been committed to the Persistent Store.
Rarely, an exception will be thrown if Mac OS X 10.5 is used AND
|managedObject| has zero properties defined. If all your NSManagedObject's
in the data model have at least one property, this will not be an issue.
Property == Attributes and Relationships
Mac OS X 10.4 and earlier are not supported, and will throw an exception.
*/
NSParameterAssert(managedObject);
NSManagedObjectContext *moc = [self managedObjectContext];
// Check for Mac OS X 10.6+
if ([moc respondsToSelector:@selector(existingObjectWithID:error:)])
{
NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *managedObjectClone = [moc existingObjectWithID:objectID error:NULL];
if (!managedObjectClone)
return YES; // Deleted.
else
return NO; // Not deleted.
}
// Check for Mac OS X 10.5
else if ([moc respondsToSelector:@selector(countForFetchRequest:error:)])
{
// 1) Per Apple, "may" be nil if |managedObject| deleted but not always.
if (![managedObject managedObjectContext])
return YES; // Deleted.
// 2) Clone |managedObject|. All Properties will be un-faulted if
// deleted. -objectWithID: always returns an object. Assumed to exist
// in the Persistent Store. If it does not exist in the Persistent
// Store, firing a fault on any of its Properties will throw an
// exception (#3).
NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *managedObjectClone = [moc objectWithID:objectID];
// 3) Fire fault for a single Property.
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
{
// If the property throws an exception, |managedObject| was deleted.
(void)[managedObjectClone valueForKey:[propertyNames objectAtIndex:0]];
return NO; // Not deleted.
}
@catch (NSException *exception)
{
if ([[exception name] isEqualToString:NSObjectInaccessibleException])
return YES; // Deleted.
else
[exception raise]; // Unknown exception thrown.
}
}
// Mac OS X 10.4 or earlier is not supported.
else
{
NSAssert(0, @"Unsupported version of Mac OS X detected.");
}
}
OLD/abgewertet ANTWORT:
ich eine etwas bessere Methode geschrieben haben. self
ist Ihr Core Data Class/Controller.
- (BOOL)hasManagedObjectBeenDeleted:(NSManagedObject *)managedObject
{
// 1) Per Apple, "may" be nil if |managedObject| was deleted but not always.
if (![managedObject managedObjectContext])
return YES; // Deleted.
// 2) Clone |managedObject|. All Properties will be un-faulted if deleted.
NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *managedObjectClone = [[self managedObjectContext] objectWithID:objectID]; // Always returns an object. Assumed to exist in the Persistent Store. If it does not exist in the Persistent Store, firing a fault on any of its Properties will throw an exception.
// 3) Fire faults for Properties. If any throw an exception, it was deleted.
NSEntityDescription *entityDescription = [managedObjectClone entity];
NSDictionary *propertiesByName = [entityDescription propertiesByName];
NSArray *propertyNames = [propertiesByName allKeys];
@try
{
for (id propertyName in propertyNames)
(void)[managedObjectClone valueForKey:propertyName];
return NO; // Not deleted.
}
@catch (NSException *exception)
{
if ([[exception name] isEqualToString:NSObjectInaccessibleException])
return YES; // Deleted.
else
[exception raise]; // Unknown exception thrown. Handle elsewhere.
}
}
Wie James Huddleston in seiner Antwort erwähnt, zu überprüfen, ob NSManagedObject des -managedObjectContext
kehrt nil
eine „ziemlich gut“ Art und Weise ist zu sehen, wenn ein im Cache gespeicherte/abgestanden NSManagedObject wird aus dem persistenten Speicher gelöscht , aber es ist nicht immer genau, wie Apple-Staaten in ihren docs:
This method may return nil if the receiver has been deleted from its context.
Wann wird es nicht gleich Null zurückgeben?Wenn Sie einen anderen NSManagedObject die gelöschte NSManagedObject der Verwendung erwerben -objectID
wie so:
// 1) Create a new NSManagedObject, save it to the Persistant Store.
CoreData *coreData = ...;
NSManagedObject *apple = [coreData addManagedObject:@"Apple"];
[apple setValue:@"Mcintosh" forKey:@"name"];
[coreData saveMOCToPersistentStore];
// 2) The `apple` will not be deleted.
NSManagedObjectContext *moc = [apple managedObjectContext];
if (!moc)
NSLog(@"2 - Deleted.");
else
NSLog(@"2 - Not deleted."); // This prints. The `apple` has just been created.
// 3) Mark the `apple` for deletion in the MOC.
[[coreData managedObjectContext] deleteObject:apple];
moc = [apple managedObjectContext];
if (!moc)
NSLog(@"3 - Deleted.");
else
NSLog(@"3 - Not deleted."); // This prints. The `apple` has not been saved to the Persistent Store yet, so it will still have a -managedObjectContext.
// 4) Now tell the MOC to delete the `apple` from the Persistent Store.
[coreData saveMOCToPersistentStore];
moc = [apple managedObjectContext];
if (!moc)
NSLog(@"4 - Deleted."); // This prints. -managedObjectContext returns nil.
else
NSLog(@"4 - Not deleted.");
// 5) What if we do this? Will the new apple have a nil managedObjectContext or not?
NSManagedObjectID *deletedAppleObjectID = [apple objectID];
NSManagedObject *appleClone = [[coreData managedObjectContext] objectWithID:deletedAppleObjectID];
moc = [appleClone managedObjectContext];
if (!moc)
NSLog(@"5 - Deleted.");
else
NSLog(@"5 - Not deleted."); // This prints. -managedObjectContext does not return nil!
// 6) Finally, let's use the method I wrote, -hasManagedObjectBeenDeleted:
BOOL deleted = [coreData hasManagedObjectBeenDeleted:appleClone];
if (deleted)
NSLog(@"6 - Deleted."); // This prints.
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 können, wird -managedObjectContext
nicht immer zurückkehren Null, wenn ein NSManagedObject wurde gelöscht aus dem dauerhaften Speicher.
Es gibt auch eine Methode 'isInserted' ein BOOL auf NSManagedObject Rückkehr, die mein Verständnis, das gleiche bedeutet. Es ist wahrscheinlich ein bisschen sauberer, es für diesen Fall zu verwenden. –
Wie auch immer, in den meisten Fällen ist diese managedObjectContext-Prüfung ausreichend und schnell! – flypig
@de, 'isInserted' ist nur JA bis das Objekt gespeichert wird, und dann wird es NEIN. Die Dokumentation sagt das nicht, aber meine Tests beweisen es. – phatmann