2012-04-24 3 views
2

속성을 편집하는 appointment이라는 NSManagedObject가 있습니다. 사용자가 을 누를 경우 취소를 편집합니다.핵심 데이터 엔티티와 함께 ​​undoManager를 사용하는 방법

내가 (예제 코드)를 할 경우

[[appointment managedObjectContext] setUndoManager:[[NSUndoManager alloc] init]]; //however doing a nslog on undoManager still shows it as (null); 
[[[appointment managedObjectContext] undoManager] beginUndoGrouping]; 
appointment.startTime = 11; 
appointment.endTime = 12; 
appointment.customer = @"Tom"; 
[[[appointment managedObjectContext] undoManager] endUndoGrouping]; 
[[[appointment managedObjectContext] undoManager] undo]; 

beginUndoGroupingendUndoGrouping 사이의 모든 변경 변경 사항을 취소하지 않겠습니까? 이 작업을 수행하는 데는 여러 가지 방법이 있지만 올바른 방법을 찾지 못하는 것 같습니다. NSManagedObject에서 변경 사항을 취소하는 올바른 방법은 무엇입니까?

답변

7

나는 실제 사건이 아닌 사건이 진행될 순서의 예라고 생각한다.

우연히 ManagedObjectContext에 NSUndoManager를 제공하는 것을 잊었습니까?

저는 OS X에서 기본적으로 하나를 얻을 수 있다고 생각하지만, iOS에서는 특별히 제공해야합니다.

는 그런 다음 여러 MOCS를 사용하고, 실행 취소 - 관리자가이 작업을 수행 한 후, 전무 경우

managedObjectContext.undoManager = [[NSUndoManager alloc] init]; 

... 당신이 당신의 MOC를 만들 때 실행 취소 관리자를 설정해야 할, 또는 다른 코드가 다시 설정했습니다.

또한 디버깅을 위해 appointment.managedObjectContext 속성을 확인하고 nil이 아니며 유효한 MOC를 참조하는지 확인하십시오.

편집

좋아, 난 그냥 가서 간단한 모델을 사용, 빠른 테스트를 썼다. 어쩌면 당신은 당신의 주장이 실패하는 곳을보기 위해 비슷한 것을해야한다. (코드 경로에 보통의 assert를 추가 할 수있다. 나는 단위 테스트를하기 때문에 기존 프로젝트에 쉽게 추가 할 수있다.)

- (void)testUndoManager 
{ 
    NSDate *now = [NSDate date]; 
    NSManagedObjectContext *moc = [self managedObjectContextWithConcurrencyType:NSConfinementConcurrencyType]; 
    STAssertNil(moc.undoManager, @"undoManager is nil by default in iOS"); 
    moc.undoManager = [[NSUndoManager alloc] init]; 
    [moc.undoManager beginUndoGrouping]; 
    NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:EVENT_ENTITY_NAME inManagedObjectContext:moc]; 
    STAssertNotNil(moc, @"Managed Object is nil"); 
    STAssertEquals(moc, object.managedObjectContext, @"MOC of object should be same as MOC"); 
    STAssertNotNil(object.managedObjectContext.undoManager, @"undoManager of MOC should not be nil"); 
    [object setValue:now forKey:@"timestamp"]; 
    STAssertEqualObjects(now, [object valueForKey:@"timestamp"], @"Timestamp should be NOW"); 
    [moc.undoManager endUndoGrouping]; 
    STAssertEqualObjects(now, [object valueForKey:@"timestamp"], @"Timestamp should be NOW"); 
    [moc.undoManager undo]; 
    STAssertNil([object valueForKey:@"timestamp"], @"Object access should be nil because changes were undone"); 
} 

EDIT

관리 객체의 MOC 여러 조건 전무로 설정 될 수있다. 예를 들어 객체를 삭제 한 다음 모드를 저장하는 경우, 상무부는 ... 그 객체의 전무로 설정됩니다

NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:@"SomeEntity" inManagedObjectContext:moc]; 
[object.managedObjectContext deleteObject:object]; 
[moc save:0]; 
// object.managedObjectContext will be nil 

또 다른, 덜 일반적인 경우지만, 기호 메모리가있을 수 있음 MOC 관련 문제 ... ARC에서 관리 대상 객체의 MOC는 취약한 포인터입니다. 따라서 MOC가 사라지면 해당 포인터가 nil로 재설정됩니다. ARC가 아닌 경우 포인터는 이전 값을 가지며 결과는 정의되지 않습니다 ... 충돌이 발생할 수 있습니다.

그래서 managedObject 인 경우.managedObjectManager는 무기 호입니다, 가장 가능성이 범인은 다음과 같습니다 객체가 MOC

  • 개체에 삽입되지 않았다

    1. MOC
    2. 상무부는
  • +0

    예입니다. 실제로 setUndoManager를했지만 여전히이 작업을 수행 한 후에 null로 남아 있습니다. – Bot

    +0

    문서에 iOS에서 명시 적으로 실행 취소 관리자를 제공해야한다는 내용의 참조가 있습니까? –

    +0

    OK 동료가 참조를 찾았습니다. https://developer.apple.com/reference/coredata/nsmanagedobjectcontext/1506663-undomanager –

    0

    가장 큰 이유 삭제에서 삭제되었습니다 실행 취소가 작동하지 않습니다. 코어 데이터가 실행 취소 관리자를 생성 및 설정하지 않습니다 ...

    newManager = [[[NSUndoManager alloc] init] autorelease]; 
    [newManager setLevelsOfUndo:4]; 
    myManagedObjectContext.undoManager = newManager; 
    

    실행 취소/시작 취소가 필요하지 않습니다.

    이벤트 루프로 돌아가서 다음에 호출 할 때까지 실행 취소가 작동하지 않을 수도 있습니다 (부분적으로 완료되었으므로 부분적으로 가능합니다). 즉, 사용자가 실행 취소 버튼을 눌렀을 때 잘리지 않을 수 있습니다.

    아, 방금 위의 설명을 추가했습니다. 귀하의 undoManager가 null이 분명히 작동하지 않게 만들 것이므로 설정을 수행하는 코드를 게시하십시오.

    +0

    은 setUndoManager, NSLog ("% @", [[appointment managedObjectContext] undoManager])의 뒤에 업데이트 된 코드 – Bot

    +0

    으로 내 OP를 수정했습니다. nil을 표시 한 다음 약속 또는 약속 .managedObjectContext가 nil입니까? – mackworth

    +0

    약속은 다른 곳에서 데이터를 사용하고 있기 때문에 무효가 아닙니다. managedObjectContext는 nil입니다. 어떻게 설정해야합니까? 'appointment.managedObjectContext = [[CoreDataHelper sharedInstance] managedObjectContext];'? – Bot