15

데이터를 가져 오는 데 NSOperation을 사용하는 일부 코드 작업 중입니다. 사용자가 가져 오기 작업 중에 생성 된 NSManagedObject 인스턴스를 실행 취소 할 수있게하고 싶습니다.기본 스레드에서 수행되는 코어 데이터 삽입 취소

내가 알 수있는 바로는, 메인 스레드에서 수행되는 모든 작업에는 NSManagedObjectContext-undoManager을 사용할 수 없습니다. ( 별도의 스레드) 관리 객체 컨텍스트 사이

  1. 만 objectID에 통과해야 : 사용에 코어 데이터 프로그래밍 가이드 섹션에서 동시성을 지원하기 위해 감금 스레드, 우리는이 두 가지 조건이
  2. 관리 대상 객체 은 objectID를 사용하기 전에 컨텍스트에 저장해야합니다. 관리 객체들이 공유 할 수 있습니다 전에 대중 저장 (NSPersistentStore)에 개인 저장 (NSManagedObjectContext)에서 이동해야하기 때문에

이 의미가 있습니다.

메시지 -save:도 실행 취소 스택의 관리 개체를 제거합니다. 같은 가이드의 메모리 관리 사용하여 코어 데이터 섹션에서 :

는 에게
자신의 상황까지 자신의 상황에 맞는 에 의해 유지됩니다 변경 (삽입, 삭제, 또는 업데이트) 보류중인 객체가 전송 관리

는 저장 : 재설정 또는 롤백 취소 메시지 또는 의 적절한 실행 취소 횟수는 변경 사항을 취소합니다.

나는이 문제를 해결하기 위해 여러 가지를 시도했다, 모든 것이 결국 작업 주 스레드에서 발생하는 대량 다시 리드 (와 비치 볼을 회전합니다.) 얻기에 모든 단서가 꺼져 만든 개체 작업 취소 메인 스레드가 매우 감사하게 될 것입니다. rdar://problem/8977725

+0

이 작업으로 삽입 된 모든 관리 객체 ID의 로그를 유지하지 않는 이유는 무엇입니까? 그렇게하면 사용자가 롤백을 원할 경우 단순히 반복하여 개체를 삭제할 수 있습니다. 돌연변이를 롤백해야하는 경우에도 키/값 변경 사항을 기록하는 것은 그리 어렵지 않습니다. 실행 매니저 (Undo Manager)에 이것을 넣으려고하는 것보다 간단합니다. – ImHuntingWabbits

+0

위의 의견에 관해서는 어떻게 redo를 건의하겠습니까? – wbyoung

답변

0

하지 전문가,하지만 난 당신이 다음 병합 작업을 수행하기 위해 두 번째 컨텍스트를 생성하기 만 할거야 어떻게 생각 : -

향상 레이더가 제출되었습니다 함께 두 문맥. 병합을 실행 취소 단계로 관리 할 수 ​​있어야합니다. 사용자가 염려하는 한 전체 작업 세트를 하나의 실행 취소 단계로 취급하는 경우에만 작동합니다.

+0

이미 가져온 컨텍스트의 변경 내용을 주 스레드의 컨텍스트로 전파하기 위해 -mergeChangesFromContextDidSaveNotification을 수행하고 있습니다. 문제는 병합이 이미 영구 저장소에있는 데이터로 개체 그래프를 조정한다는 점입니다. 주 스레드의 NSManagedObjectContext에는 영구 저장소에 기록해야하는 -insertedObjects 또는 -updatedObjects가 없습니다. – chockenberry

0

백그라운드 스레드에 별도의 컨텍스트를 사용한다고 가정하고 완료되면 [[backgroundContext undoManager] undo]을 포어 그라운드 스레드의 실행 취소 스택에 푸시? 그런 일은 한번도 해본 적이 없지만, 내 머리 꼭대기에서 나는 그것이 작동해서는 안되는 이유를 생각할 수 없다.

+0

"[[backgroundContext undoManager] undo]가 포 그라운드 스레드의 실행 취소 스택으로 무엇을 의미합니까? 내가 실행 취소 스택의 내용을 개인적으로 알 수있는 내용은 다음과 같습니다. – chockenberry

+0

[[[foregroundContext undoManager] prepareWithInvocationTarget : [backgroundContext undoManager]] undo]; (실제로는 backgroundContext도 저장해야합니다 ...) –

+0

여기에는 몇 가지 문제점이 있습니다. backgroundContext는 foregroundContext가 장기간 대상으로 지정할 수없는 짧은 스레드입니다. 또한 backgroundContext가 -save를 전송하자마자 : 포어 그라운드 작업이 작동하기 위해 실행 취소 스택에 아무 ​​것도 없습니다. – chockenberry

0

하나의 옵션은 가져 오기 스레드를 영구화하는 것일 수 있습니다. 스레드가 가져 오기를 마친 경우에도 유휴 루프 상태가됩니다. 이 방법으로 스레드 된 ManagedObjectContext가 적절한 스레드에 지속됩니다. 그런 다음 사용자가 변경 사항을 실행 취소하려면 스레드에 메시지를 보내어 undomanager를 사용하십시오.

+0

여기서 문제는 관리 객체 컨텍스트가 -save :가 발생할 때까지 서로의 삽입 된 객체를 알지 못한다는 것입니다. 어느 순간에 실행 취소 스택이 찢어집니다 ... – chockenberry

2

이 답변은 아마도 약간 앞뒤로 보일 것입니다. 문제를 올바르게 이해하면 가져 오기를 수행하지만 가져 오기가 완료되면 사용자가 가져 오기에서 저장되는 항목을 선택할 수있게하려고합니까?

그 내용이 정확하지 않으면 제 가정을 수정하십시오.이 대답이 업데이트됩니다.

가 올 경우 당신이 할 수있는 것은 :

  1. 배열에

    NSEntityDescription *myEntity = ... //Entity from your context 
    [[NSManagedObject alloc] initWithEntity:myEntity 
         insertIntoManagedObjectContext:nil]; 
    
  2. 스토어 이들 엔티티에 배경 오브젝트 작성을 변경

    .

  3. 필요에 따라 엔티티를 기본 스레드로 다시 전달하십시오.
  4. 보관하고 싶지 않은 모든 물건에 붙어 있습니다.
  5. 보관하고 싶은 사람은 [myMainContext insertObject:managedObject]으로 전화하십시오.
  6. NSManagedObjectContext에서 저장을 수행하십시오. 이 단체는 NSManagedObjectContext의 일부가 아닌 아직 그들은 단지 메모리에 존재하고 그들은 아직 NSManagedObjectContext에 묶여 있지 않기 때문에 스레드 안전해야하기 때문에

.

이것은 물론 이론적이며 테스트가 필요할 것입니다. 그러나 그것은 당신의 목표를 달성해야합니다.

+0

[initWithEntity : entity insertIntoManagedObjectContext : nil]은 올바른 코드입니까? 임시 객체에 대한 메모리 내 MOC를 생성하지 않아도됩니까? –

+0

필요하지 않습니다. NSEntityDescription을 해결하려면 MOC가 필요하지만 MO는 MOC와 연결될 필요가 없습니다. 그것은 저장 될 MOC와 연관 될 필요가 있습니다. –

+0

알아두면 좋을 것. 정보 주셔서 감사합니다. –

0

그것은 당신이를 생각했습니다 당신은 가능성 만 기존 undoManager를 사용하는 솔루션을 찾고 있지만, 매우 가능성이 그냥 경우 : 당신이 개체를 삽입하고 기존 업데이트하지 않는 때문에

, 당신이 각각의 일괄 처리를 가져올 때 트랜잭션 ID로 태그를 붙일 수있는 권한이 있습니다. 실행 취소의 경우 백그라운드 스레드에서 삭제됩니다. 단순 증가 태그 NSNumber이면 충분합니다.

명료하지 만 실용적입니다.