[objective-c] 임시 NSManagedObject 인스턴스를 처리하는 방법은 무엇입니까?

NSManagedObject인스턴스 를 만들고 몇 가지 작업을 수행 한 다음이를 폐기하거나 sqlite db에 저장해야합니다. 문제는 NSManagedObject연결되지 않은 인스턴스를 만들 수 없다는 NSManagedObjectContext것입니다. 즉, DB에있는 일부 개체가 필요하지 않다고 결정한 후 어떻게 든 정리해야합니다.

이를 처리하기 위해 동일한 코디네이터를 사용하여 메모리 내 저장소를 만들고 assignObject:toPersistentStore.Now 를 사용하여 임시 개체를 배치 하고 있습니다. 이러한 임시 개체가 데이터에 도달하지 않도록하려면 어떻게해야하나요? 두 상점 컨텍스트에 공통입니까? 아니면 그러한 작업에 대해 별도의 컨텍스트를 만들어야합니까?


UPD :

이제 메모리 내 저장소에 대해 별도의 컨텍스트를 만드는 방법을 생각하고 있습니다. 한 컨텍스트에서 다른 컨텍스트로 개체를 어떻게 이동합니까? [context insertObject :]를 사용하십니까? 이 설정에서 제대로 작동합니까? 객체 그래프에서 하나의 객체를 삽입하면 전체 그래프도 컨텍스트에 삽입됩니까?



답변

참고 : 이 답변은 매우 오래되었습니다. 전체 기록을 보려면 댓글을 참조하세요. 이후 권장 사항이 변경되었으며 더 이상 연결되지 않은 NSManagedObject인스턴스를 사용하지 않는 것이 좋습니다 . 현재 권장 사항은 임시 자식 NSManagedObjectContext인스턴스 를 사용하는 것 입니다.

원래 답변

이를 수행하는 가장 쉬운 방법 NSManagedObject은 연결된 NSManagedObjectContext.

NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC];
NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

그런 다음 저장하려는 경우 :

[myMOC insertObject:unassociatedObject];
NSError *error = nil;
if (![myMoc save:&error]) {
  //Respond to the error
}


답변

iOS5는 Mike Weller의 대답에 대한 더 간단한 대안을 제공합니다. 대신 자식 NSManagedObjectContext를 사용하십시오 . NSNotificationCenter를 통해 트램폴린이 필요하지 않습니다.

하위 컨텍스트를 만들려면 :

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
childContext.parentContext = myMangedObjectContext;

그런 다음 자식 컨텍스트를 사용하여 개체를 만듭니다.

NSManagedObject *o = [NSEntityDescription insertNewObjectForEntityForName:@"MyObject" inManagedObjectContext:childContext];

변경 사항은 하위 컨텍스트가 저장 될 때만 적용됩니다. 따라서 변경 사항을 취소하려면 저장하지 마십시오.

관계에는 여전히 제한이 있습니다. 즉, 다른 컨텍스트의 개체에 대한 관계를 만들 수 없습니다. 이 문제를 해결하려면 objectID를 사용하여 자식 컨텍스트에서 개체를 가져옵니다. 예.

NSManagedObjectID *mid = [myManagedObject objectID];
MyManagedObject *mySafeManagedObject = [childContext objectWithID:mid];
object.relationship=mySafeManagedObject;

하위 컨텍스트를 저장하면 변경 사항이 상위 컨텍스트에 적용됩니다. 상위 컨텍스트를 저장하면 변경 사항이 유지됩니다.

자세한 설명 은 wwdc 2012 세션 214 를 참조하십시오 .


답변

이러한 종류의 작업을 수행하는 올바른 방법은 새로운 관리 개체 컨텍스트를 사용하는 것입니다. 동일한 영구 저장소를 사용하여 관리되는 개체 컨텍스트를 만듭니다.

NSManagedObjectContext *tempContext = [[[NSManagedObjectContext alloc] init] autorelease];
[tempContext setPersistentStore:[originalContext persistentStore]];

그런 다음 새 개체를 추가하고 변경합니다.

저장할 때가되면 tempContext에서 [tempContext save : …]를 호출하고 저장 알림을 처리하여 원래 컨텍스트에 병합해야합니다. 객체를 버리려면이 임시 컨텍스트를 해제하고 잊어 버리십시오.

따라서 임시 컨텍스트를 저장하면 변경 사항이 스토어에 유지되며 해당 변경 사항을 기본 컨텍스트로 다시 가져 오면됩니다.

/* Called when the temp context is saved */
- (void)tempContextSaved:(NSNotification *)notification {
    /* Merge the changes into the original managed object context */
    [originalContext mergeChangesFromContextDidSaveNotification:notification];
}

// Here's where we do the save itself

// Add the notification handler
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(tempContextSaved:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:tempContext];

// Save
[tempContext save:NULL];
// Remove the handler again
[[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:NSManagedObjectContextDidSaveNotification
                                              object:tempContext];

이것은 다중 스레드 코어 데이터 작업을 처리해야하는 방법이기도합니다. 스레드 당 하나의 컨텍스트.

관계를 추가하기 위해이 임시 컨텍스트에서 기존 객체에 액세스해야하는 경우 객체의 ID를 사용하여 다음과 같은 새 인스턴스를 가져와야합니다.

NSManagedObject *objectInOriginalContext = ...;
NSManagedObject *objectInTemporaryContext = [tempContext objectWithID:[objectInOriginalContext objectID]];

NSManagedObject잘못된 컨텍스트에서 를 사용하려고하면 저장하는 동안 예외가 발생합니다.


답변

nil 컨텍스트에서 임시 객체를 만드는 것은 실제로 컨텍스트가! = nil 인 객체와 관계를 갖기 전까지는 잘 작동합니다!

괜찮은지 확인하십시오.


답변

당신이 설명하는 것은 정확히 무엇을위한 NSManagedObjectContext것입니다.

에서 코어 데이터 기본 사항 : 코어 데이터 프로그래밍 가이드

관리되는 개체 컨텍스트를 지능형 스크래치 패드로 생각할 수 있습니다. 영구 저장소에서 개체를 가져올 때 임시 복사본을 스크래치 패드로 가져와 개체 그래프 (또는 개체 그래프 모음)를 형성합니다. 그런 다음 원하는대로 이러한 개체를 수정할 수 있습니다. 그러나 실제로 이러한 변경 사항을 저장하지 않는 한 영구 저장소는 변경되지 않습니다.

핵심 데이터 프로그래밍 가이드 : 관리 개체 유효성 검사

이것은 또한 “스크래치 패드”를 나타내는 관리 객체 컨텍스트의 개념을 뒷받침합니다. 일반적으로 관리 객체를 스크래치 패드로 가져 와서 궁극적으로 변경 사항을 커밋하거나 삭제하기 전에 원하는대로 편집 할 수 있습니다.

NSManagedObjectContexts는 경량으로 설계되었습니다. 당신은 그것들을 마음대로 만들고 버릴 수 있습니다. 이것은 영구 저장소 조정자이며 “무거운”의존성입니다. 단일 영구 저장소 코디네이터는 이와 관련된 여러 컨텍스트를 가질 수 있습니다. 구식 스레드 제한 모델에서 이는 각 컨텍스트에 동일한 영구 저장소 코디네이터를 설정하는 것을 의미합니다. 오늘날 이는 중첩 된 컨텍스트를 영구 저장소 코디네이터와 연관된 루트 컨텍스트에 연결하는 것을 의미합니다.

컨텍스트를 만들고 해당 컨텍스트 내에서 관리되는 개체를 만들고 수정합니다. 이를 유지하고 변경 사항을 전달하려면 컨텍스트를 저장하십시오. 그렇지 않으면 폐기하십시오.

독립적으로 관리되는 개체를 만들려고하면 NSManagedObjectContext문제가 발생합니다. Core Data는 궁극적으로 개체 그래프에 대한 변경 추적 메커니즘입니다. 이 때문에 관리되는 개체는 실제로 관리되는 개체 컨텍스트의 일부입니다 . 문맥은 자신의 라이프 사이클을 관찰 하고, 문맥없이 모든 관리 객체의 기능이 제대로 작동합니다.


답변

임시 개체의 사용에 따라 위의 권장 사항에 대한 몇 가지주의 사항이 있습니다. 내 사용 사례는 임시 개체를 만들고 뷰에 바인딩하려는 것입니다. 사용자가이 개체를 저장하도록 선택하면 기존 개체에 대한 관계를 설정하고 저장하려고합니다. 이러한 값을 유지하기 위해 임시 개체를 만드는 것을 방지하기 위해이 작업을 수행하고 싶습니다. (예, 사용자가보기 내용을 저장할 때까지 기다렸다가보기 내용을 가져올 수 있지만 이러한보기를 테이블 내부에 넣고이를 수행하는 논리가 덜 우아합니다.)

임시 개체에 대한 옵션은 다음과 같습니다.

1) (선호) 자식 컨텍스트에서 임시 개체를 만듭니다. 개체를 UI에 바인딩하고 개체 접근자가 자식 컨텍스트에서 호출된다는 것을 보장 할 수 없기 때문에 작동하지 않습니다. (다른 설명이있는 문서를 찾지 못 했으므로 가정해야합니다.)

2) nil 개체 컨텍스트로 임시 개체를 만듭니다. 이것은 작동하지 않으며 데이터 손실 / 손상을 초래합니다.

내 솔루션 : nil 객체 컨텍스트로 임시 객체를 생성하여이 문제를 해결했지만 객체를 # 2로 삽입하지 않고 저장할 때 모든 속성을 기본 컨텍스트에서 생성 한 새 객체에 복사합니다. NSManagedObject 하위 클래스에서 cloneInto :라는 지원 메서드를 만들었습니다.이 메서드를 사용하면 모든 개체에 대한 특성과 관계를 쉽게 복사 할 수 있습니다.


답변

나를 위해 마커스의 대답이 작동하지 않았습니다. 나를 위해 일한 것은 다음과 같습니다.

NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC];
NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

그런 다음 저장하기로 결정한 경우 :

[myMOC insertObject:unassociatedObjet];
NSError *error = nil;
[myMoc save:&error];
//Check the error!

우리는 또한 그것을 해제하는 것을 잊지 말아야합니다

[unassociatedObject release]