2010-02-20 4 views
7

사용자가 항목을 추가 할 수있는 iPhone 응용 프로그램을 만들려고합니다. 그가 새 항목을 누르면 상자에 정보가 있는지 묻는 팝업이 나타납니다. 그런 다음 "취소"또는 "저장"을 눌러 데이터를 버리거나 디스크에 저장하십시오.NSUndoManager가 코어 데이터로 작업하지 않습니다.

저축을 위해, 나는 꽤 잘 작동하는 핵심 데이터 프레임 워크를 사용하고 있습니다. 그러나 "취소"버튼을 사용할 수 없습니다. 정보를 묻는 창이 나타나면 관리 대상 객체 컨텍스트 (MOC)에 새 객체를 만듭니다. 그런 다음 사용자가 취소를 누르면 MOC에 속한 NSUndoManager를 사용하려고합니다.

중첩 된 그룹이있을 수 있으므로 중첩 된 실행 취소 그룹을 사용하여이 작업을 수행하고 싶습니다.

이것을 테스트하려면 간단한 응용 프로그램을 작성했습니다. 응용 프로그램은 핵심 데이터가 활성화 된 "Window 기반 응용 프로그램"템플릿 일뿐입니다. 핵심 데이터 모델의 경우, 정수 속성 "x"를 갖는 "Entity"라는 단일 엔티티를 작성합니다. 그런 다음 applicationDidFinishLaunching 내부에 다음 코드를 추가합니다.

- (void)applicationDidFinishLaunching:(UIApplication *)application {  

    // Override point for customization after app launch  

    unsigned int x=arc4random()%1000; 
    [self.managedObjectContext processPendingChanges]; 
    [self.managedObjectContext.undoManager beginUndoGrouping]; 

    NSManagedObject *entity=[NSEntityDescription insertNewObjectForEntityForName:@"Entity" 
                 inManagedObjectContext:self.managedObjectContext]; 
    [entity setValue:[NSNumber numberWithInt:x] forKey:@"x"]; 
    NSLog(@"Insert Value %d",x); 

    [self.managedObjectContext processPendingChanges]; 
    [self.managedObjectContext.undoManager endUndoGrouping]; 
    [self.managedObjectContext.undoManager undoNestedGroup]; 

    NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init]; 
    NSEntityDescription *entityEntity=[NSEntityDescription entityForName:@"Entity" 
               inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entityEntity]; 
    NSArray *result=[self.managedObjectContext executeFetchRequest:fetchRequest error:nil]; 
    for(entity in result) { 
    NSLog(@"FETCHED ENTITY %d",[[entity valueForKey:@"x"] intValue]); 
    } 

    [window makeKeyAndVisible]; 
} 

아이디어가 간단합니다. 새 Entity 객체를 삽입하고 실행 취소 한 다음 MOC에있는 모든 Entity 객체를 가져 와서 인쇄하십시오. 모든 것이 올바르게 작동하면 끝에는 아무 것도 없어야합니다. 나는 그것의 생성을 취소하려고 후

[Session started at 2010-02-20 13:41:49 -0800.] 
2010-02-20 13:41:51.695 Untitledundotes[7373:20b] Insert Value 136 
2010-02-20 13:41:51.715 Untitledundotes[7373:20b] FETCHED ENTITY 136 

당신이 볼 수 있듯이, 객체가 MOC에 존재 :

그러나,이 출력을 얻을. 내가 뭘 잘못하고 있는지에 대한 제안이 있으십니까?

+0

안녕 임 매우 똑같은 문제가 있습니다. 해결책을 찾았습니까? "undoNestedGroup"대신 "undo"를 사용해 보셨습니까? 감사합니다. gonso – gonso

답변

13

문제는 OS X과 달리 iPhone 관리 객체 컨텍스트에 실행 취소 관리자가 기본적으로 포함되어 있지 않기 때문에 발생합니다. 명시 적으로 추가해야합니다. managedObjectContext 속성에 대한 애플 대리자에서 생성 된 코드는 다음과 같이 할 수

변경이 :

- (NSManagedObjectContext *) managedObjectContext { 

    if (managedObjectContext != nil) { 
     return managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     //add the following 3 lines of code 
     NSUndoManager *undoManager = [[NSUndoManager alloc] init]; 
     [managedObjectContext setUndoManager:undoManager]; 
     [undoManager release]; 
     [managedObjectContext setPersistentStoreCoordinator: coordinator]; 
    } 

    return managedObjectContext; 

} 

그 변경 한 후 2 차 로그 메시지가 더 이상 인쇄되지 않습니다. 도움이

희망 ...

데이브

+2

Google 검색에서 비슷한 질문을하는 동안 발견되었습니다. Dave, undoManager가 기본적으로 nil이라는 좋은 이유가 있다고 가정합니다. 마찬가지로, 내가 이것을 수행한다면, 나는 기억과 관련된 두통을 갖게 될 것인가? –

4

나는 데이브 접근 방식을 시도했지만 나를 위해 작동하지 않았다. 마침내 애플의 사례에서 해결책을 찾았습니다. CoreDataBooks

트릭은 당신이 애플 리케이션 컨텍스트와 코디네이터를 공유하는 새로운 컨텍스트를 만드는 것입니다. 변경 사항을 버리려면 필요한 작업을 수행 할 필요가 없습니다. 새 컨텍스트 개체를 삭제하십시오. 코디네이터를 공유하기 때문에 기본 컨텍스트가 저장됩니다.

여기 내 적응 형 버전입니다. 여기에서 임시 컨텍스트에 대한 정적 개체를 사용하여 새 ChannelMO 개체를 만듭니다.

//Gets a new ChannelMO that is part of the addingManagedContext 
+(ChannelMO*) getNewChannelMO{ 

    // Create a new managed object context for the new channel -- set its persistent store coordinator to the same as that from the fetched results controller's context. 
    NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init]; 
    addingManagedObjectContext = addingContext; 

    [addingManagedObjectContext setPersistentStoreCoordinator:[[self getContext] persistentStoreCoordinator]]; 

    ChannelMO* aux = (ChannelMO *)[NSEntityDescription insertNewObjectForEntityForName:@"ChannelMO" inManagedObjectContext:addingManagedObjectContext]; 
    return aux; 
} 

+(void) saveAddingContext{ 
    NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; 
    [dnc addObserver:self selector:@selector(addControllerContextDidSave:) 
       name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext]; 

    NSError *error; 
    if (![addingManagedObjectContext save:&error]) { 
     // Update to handle the error appropriately. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     exit(-1); // Fail 
    } 
    [dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext]; 

    // Release the adding managed object context. 
    addingManagedObjectContext = nil; 
} 

가 나는

Gonso

+0

저장에 실패하면 어떻게됩니까? 이미 컨텍스트에 추가 된 변경 사항을 어떻게 취소하고 실패를 일으켰습니까? 예 : 확인. – malhal

0

그것은 작동합니다 도움이되기를 바랍니다. 실행 취소 관리자를 managedObjectContext에 올바르게 지정 했습니까? 당신이 올바르게했다면, 그것은 기본적으로 실행 취소 등록이 가능하고, 당신은 잘해야합니다.핵심 데이터 here에 관한 좋은 기사가 있습니다. 핵심 데이터 및 NSUndoManager here에 대한 좋은 자습서가 있습니다. 희망이 도움이됩니다.

관련 문제