2013-07-16 2 views
0

에서 Core Data 객체를 추가하면 데이터를 추가 할 때 다양한 뷰 컨트롤러 (VC)를 전달할 때의 문제에 당혹 스럽습니다. 사과의 예 (http://developer.apple.com/library/ios/#samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html)로 제공 CoreDataRecipes 프로젝트들은 다음과 같은 방법코어 데이터에 익숙해지기 위해 섹터

사용자가 마스터 테이블보기에서 제시 조리법의 목록에 조리법을 추가하고 싶어

, 그리고에게 사용의 예를 들어

,

- (void)add:(id)sender { 
// To add a new recipe, create a RecipeAddViewController. Present it as a modal view so that the user's focus is on the task of adding the recipe; wrap the controller in a navigation controller to provide a navigation bar for the Done and Save buttons (added by the RecipeAddViewController in its viewDidLoad method). 
RecipeAddViewController *addController = [[RecipeAddViewController alloc] initWithNibName:@"RecipeAddView" bundle:nil]; 
addController.delegate = self; 

Recipe *newRecipe = [NSEntityDescription insertNewObjectForEntityForName:@"Recipe" inManagedObjectContext:self.managedObjectContext]; 
addController.recipe = newRecipe; 

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addController]; 
[self presentModalViewController:navigationController animated:YES]; 

[navigationController release]; 
[addController release]; 
} 

이 새로 생성 된 객체 (레시피)을 RecipeAddViewController에 전달됩니다 : 추가 버튼을 안타 (RecipeListTableViewController라고 함) 마스터 테이블 뷰 컨트롤러는 다음과 같은 새로운 관리 객체 (레시피)을 생성한다. 다음과 같이 RecipeAddViewController는 두 가지 방법, 저장 및 취소가 있습니다

- (void)save { 

recipe.name = nameTextField.text; 

NSError *error = nil; 
if (![recipe.managedObjectContext save:&error]) { 
    /* 
    Replace this implementation with code to handle the error appropriately. 

    abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button. 
    */ 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
}  

[self.delegate recipeAddViewController:self didAddRecipe:recipe]; 

가}

- (void)cancel { 

[recipe.managedObjectContext deleteObject:recipe]; 

NSError *error = nil; 
if (![recipe.managedObjectContext save:&error]) { 
    /* 
    Replace this implementation with code to handle the error appropriately. 

    abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button. 
    */ 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
}  

[self.delegate recipeAddViewController:self didAddRecipe:nil]; 

}

내가이 디자인 접근 방식에 대해 의아해입니다. 사용자가 실제로 새로운 래서 피 이름을 입력하고 새 객체를 저장하기를 원한다는 것을 알기 전에 RecipeListViewController가 객체를 생성해야하는 이유는 무엇입니까? 왜 managedObjectContext를 addRecipeController에 전달하지 않고 사용자가 save를 눌렀을 때까지 객체를 생성하고 해당 필드에 데이터를 채울 때까지 기다리십시오. 결국 추가 할 새로운 레서피가 없으면 새 객체를 삭제하지 않아도됩니다. 또는 RecipeListViewController와 RecipeAddController 사이에서 recipe 이름 (문자열)을 앞뒤로 전달하지 않는 이유는 무엇입니까?

내가 managedObjectContexts을 통과하는 내가 segues 사이에 문자열을 통과 할 때 이해하기 위해 고군분투하고 있기 때문에, 언제, 객체를 전달하는 데 요구하고있어 ...

많은 감사 어떤 지침 포함. 문제가되는 디자인 철학에 대한 토론 링크.

답변

1

문제는 NSManagedObject이 컨텍스트 없이는 살 수 없다는 것입니다. 컨텍스트에 레서피를 추가하지 않으면 해당 레서피의 모든 속성을 "일반"인스턴스 변수에 저장해야합니다. 사용자가 탭을 저장하면이 인스턴스 변수에서 레시피를 생성합니다.

이것은 AddViewController의 큰 문제는 아니지만 어떤 viewController를 사용하여 래서 피를 편집 하시겠습니까? 아마 AddViewController를 재사용 할 수 있습니다. 그러나 모든 데이터를 인스턴스 변수로 저장하면 레서피에서 모든 데이터를 가져와 인스턴스 변수에 저장해야하기 때문에 조금 추한 결과를 얻습니다. 그리고 완료되면 리버스 작업을 수행해야합니다.

그래서 나는 보통 다른 접근법을 사용합니다. 편집을 위해 편집 컨텍스트를 사용합니다 (또는 기본적으로 편집 만하는 추가 작업).

- (void)presentRecipeEditorForRecipe:(MBRecipe *)recipe { 
    NSManagedObjectContext *editingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
    editingContext.parentContext = self.managedObjectContext; 
    MBRecipe *recipeForEditing; 
    if (recipe) { 
     // get same recipe inside of the editing context. 
     recipeForEditing = (MBRecipe *)[editingContext objectWithID:[recipe objectID]]; 
     NSParameterAssert(recipeForEditing); 
    }  
    else { 
     // no recipe for editing. create new one 
     recipeForEditing = [MBRecipe insertInManagedObjectContext:editingContext]; 
    } 

    // present editing view controller and set recipeForEditing and delegate 
} 

꽤 직선적 인 코드. 편집에 사용되는 새로운 하위 컨텍스트를 작성합니다. 그리고 그 상황에서 편집법을 얻습니다.

이 아님 EditViewController에 컨텍스트를 저장해야합니다! Recipe의 모든 원하는 속성을 설정하기 만하면됩니다.

사용자가 "취소"또는 "완료"를 누르면이 대리자 메서드가 호출됩니다. editingContext와 컨텍스트를 저장하거나 아무것도하지 않습니다.

- (void)recipeEditViewController:(MBRecipeEditViewController *)editViewController didFinishWithSave:(BOOL)didSave { 
    NSManagedObjectContext *editingContext = editViewController.managedObjectContext; 
    if (didSave) { 
     NSError *error; 
     // save editingContext. this will put the changes into self.managedObjectContext 
     if (![editingContext save:&error]) { 
      NSLog(@"Couldn't save editing context %@", error); 
      abort(); 
     } 

     // save again to save changes to disk 
     if (![self.managedObjectContext save:&error]) { 
      NSLog(@"Couldn't save parent context %@", error); 
      abort(); 
     } 
    } 
    else { 
     // do nothing. the changes will disappear when the editingContext gets deallocated 
    } 
    [self dismissViewControllerAnimated:YES completion:nil]; 
    // reload your UI in `viewWillAppear:` 
} 
+0

감사합니다. 이것은 매우 우아 해 보였고 내가 걱정했던 것, 즉 addRecipe 프로세스의 중단으로 인해 managedObjectContext에 빈 레코드가 남을 수 있습니다. 나는이 접근법에 관해 몇 가지 추가 질문을한다. 먼저, 동시성 유형을 읽고 궁금해서 편집 컨텍스트에 대해 NSMainQueueConcurrencyType을 선택합니다. 둘째, 왜 NSParameterAssert (recipeForEditing)입니까? 필요한거야? –

+0

업데이트 : Matthias B.의 접근 방식을 사용하려고하면 런타임에 다음 오류가 발생합니다. *** 캐치되지 않은 예외 'NSInvalidArgumentException'으로 인해 응용 프로그램을 종료합니다. 이유 : '부모 NSManagedObjectContext는 NSPrivateQueueConcurrencyType 또는 NSMainQueueConcurrencyType을 사용해야합니다.' ...이 때 여부를 내가이 유형 중 하나를 만들 필요가있는 응용 프로그램 대리인에서 원래 NSManagedObjectContext 선언하고 여부를 질문을 구걸, 그리고, 그렇다면 어떤 우수한 무엇입니까? –

관련 문제