`NSManagedObject`가 삭제되었는지 어떻게 알 수 있습니까?
나는이 NSManagedObject
삭제 된 것을, 그 관리 객체를 포함하는 컨텍스트가 저장되었습니다. Core Data가 다음 저장 작업 중에 객체를 삭제하도록 영구 저장소에 요청하면 isDeleted
반환 된다는 것을 이해합니다 YES
. 그러나 이미 저장이 수행되었으므로를 isDeleted
반환합니다 NO
.
여부를 알 수있는 좋은 방법은 무엇입니까 NSManagedObject
삭제 된 후에 는 포함 컨텍스트가 저장되어있는가?
(삭제 된 관리 대상 개체를 참조하는 개체가 아직 삭제를 인식하지 못하는 이유가 궁금한 경우 삭제 및 컨텍스트 저장이를 사용하여 삭제 및 저장을 수행 한 백그라운드 스레드에 의해 시작 되었기 때문 performSelectorOnMainThread:withObject:waitUntilDone:
입니다.)
관리되는 개체의 컨텍스트를 확인하는 것이 작동하는 것 같습니다.
if (managedObject.managedObjectContext == nil) {
// Assume that the managed object has been deleted.
}
Apple의 문서에서 managedObjectContext
...
이 메서드는 수신자가 컨텍스트에서 삭제 된 경우 nil을 반환 할 수 있습니다.
수신자가 오류 인 경우이 메서드를 호출해도 실행되지 않습니다.
둘 다 좋은 것 같습니다.
업데이트 : 특별히 사용하여 검색된 관리 개체 objectWithID:
가 삭제 되었는지 테스트하려는 경우 Dave Gallagher의 답변을 확인하십시오 . 그는 objectWithID:
삭제 된 개체의 ID를 사용하여 호출 하면 반환 된 개체는 nil로 설정 되지 않은 오류가 될 것이라고 지적합니다 managedObjectContext
. 결과적 managedObjectContext
으로 삭제되었는지 여부를 테스트하기 위해 단순히 확인할 수는 없습니다 . 가능하면 사용하십시오 existingObjectWithID:error:
. 예를 들어 Mac OS 10.5 또는 iOS 2.0을 대상으로하고 있지 않은 경우 삭제 테스트를 위해 다른 작업을 수행해야합니다. 자세한 내용은 그의 답변 을 참조하십시오.
업데이트 : 아래 토론에서 James Huddleston 의 아이디어를 기반으로 한 개선 된 답변 입니다.
- (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.");
}
}
오래되었거나 더 이상 사용되지 않는 답변 :
나는 약간 더 나은 방법을 썼다. self
Core Data 클래스 / 컨트롤러입니다.
- (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.
}
}
로 제임스 허들 스턴이 NSManagedObject의 있는지 확인, 그의 대답에 언급 -managedObjectContext
반환 nil
캐시 / 오래된 NSManagedObject가 영구 저장소에서 삭제 된 경우보고의 "매우 좋은"방법이지만, 애플이 자신의 문서에서 상태로 항상 정확하지는입니다 :
이 메서드 는 수신자가 컨텍스트에서 삭제 된 경우 nil을 반환 할 수 있습니다 .
언제 nil을 반환하지 않습니까? 다음 -objectID
과 같이 삭제 된 NSManagedObject를 사용하여 다른 NSManagedObject를 획득하는 경우 :
// 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.");
다음은 출력물입니다.
2 - Not deleted.
3 - Not deleted.
4 - Deleted.
5 - Not deleted.
6 - Deleted.
보시다시피 -managedObjectContext
, NSManagedObject가 영구 저장소에서 삭제 된 경우 항상 nil을 반환하지는 않습니다.
I fear the discussion in the other answers is actually hiding the simplicity of the correct answer. In pretty much all cases, the correct answer is:
if ([moc existingObjectWithID:object.objectID error:NULL])
{
// object is valid, go ahead and use it
}
The only cases this answer doesn't apply in is:
- If you are targetting Mac OS 10.5 or earlier
- If you are targetting iOS 2.0 or earlier
- If the object/context has not been saved yet (in which case you either don't care because it won't throw a
NSObjectInaccessibleException
, or you can useobject.isDeleted
)
Due to my recent experience implementing iCloud in my iOS app that relies on Core Data for persistence, I realized that the best way is observing the framework's notifications. At least, better than relying on some obscure methods that may, or may not tell you if some managed object was deleted.
For 'pure' Core Data apps you should observe NSManagedObjectContextObjectsDidChangeNotification on the main thread. The notification's user info dictionary contains sets with the managed objects' objectIDs that were inserted, deleted and updated.
If you find your managed object's objectID in one of these sets, then you can update your application and UI in some nice way.
That's it... for more information, give a chance to Apple's Core Data Programming Guide, Concurrency with Core Data chapter. There's a section "Track Changes in Other Threads Using Notifications", but don't forget to check the previous one "Use Thread Confinement to Support Concurrency".
try this method:
if (manageObject.deleted) {
// assume that the managed object has been deleted.
}
Verified in Swift 3, Xcode 7.3
You can also simply PRINT
the memory references of each context and check
(a) if the context exists,
(b) if the contexts of 2 objects are different
eg:( Book and Member being 2 different objects)
print(book.managedObjectContext)
print(member.managedObjectContext)
It would print something like this if the contexts exist but are different
0x7fe758c307d0
0x7fe758c15d70
'program tip' 카테고리의 다른 글
CSS Calc 대안 (0) | 2020.11.10 |
---|---|
Tomcat 클래스 경로에 디렉토리 추가 (0) | 2020.11.10 |
다시 인코딩하지 않고 mp4 비디오 회전 (0) | 2020.11.10 |
UIWebView에서 사용자 에이전트 변경 (0) | 2020.11.10 |
임시 테이블에서 필드 이름을 검색하는 방법 (SQL Server 2008) (0) | 2020.11.10 |