Основные данные - отношения неожиданно обнуляются - PullRequest
0 голосов
/ 31 июля 2011

Я борюсь с каким-то странным поведением в Core Data.У меня довольно стандартная настройка, используя пример CoreDataBook: у меня есть RootView, который использует NSFetchedResultsController для отображения списка элементов.Предмет имеет несколько атрибутов и связей с другими сущностями.У меня есть DetailView, который я использую для создания нового элемента, а также для редактирования существующего элемента, который я представляю модально.В DetailView: viewDidLoad я создаю новый managedObjectContext, в котором я хочу внести все изменения ... если пользователь нажимает Сохранить, я сохраняю этот контекст и объединяю изменения обратно;в противном случае, если пользователь нажимает кнопку отмены, все эти изменения просто исчезают.

Эта часть «добавить новый элемент» работает нормально, но когда я выбираю строку, чтобы вызвать тот же DetailView, что и существующий элемент, одно из отношений (что хорошо отображается в RootView в отладчике)внезапно становится равным нулю, когда он представлен в DetailView.Вот код для отображения DetailView в didSelectRowAtIndexPath UITableView:

    Item *managedObject = (Item *)[self.fetchedResultsController objectAtIndexPath:indexPath];
    DetailView *childController = [[DetailView alloc] initWithNibName:@"DetailView" bundle:nil];

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:childController];    

    childController.existingItem = managedObject;

    // ** Item's relationship to Title is not nil at this point
    [self presentModalViewController:navController animated:YES];
    // ** Item's relationship Title is now nil

    [childController release];
    [navController release];

В контроллере DetailView нет ничего необычного, что могло бы вызвать это.На самом деле, у него даже нет шансов действительно нанести какой-либо ущерб ... как только он начнется, отношение существующихItem.title уже равно нулю.[istingItem - это сохраненное свойство DetailView]

Есть идеи, с чего мне начать изучать это?Последние несколько часов это сводило меня с ума.Вот некоторый код в DetailView viewDidLoad, но отношение равно nil даже до его вызова:

    // Create a new managed object context
    NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
    self.addEditContext = addingContext;
    [addingContext release];
    [self.addEditContext setPersistentStoreCoordinator:[[appDelegate managedObjectContext] persistentStoreCoordinator]];

    if (!self.existingItem) {
        self.existingItem = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext: self.addEditContext];

    }else{
        self.existingItem = (Item *)[self.addEditContext objectWithID:[self.existingItem  objectID]];
    }

Отношение заголовка устанавливается путем выбора из некоторого списка:

self.existingItem.title = selectedTitle;

В сохранении:метод, я сохраняю addEditContext и объединяю изменения с контекстом appdelegate:

    NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
    [dnc addObserver:self selector:@selector(addControllerContextDidSave:) name:NSManagedObjectContextDidSaveNotification object: self.addEditContext];

    // Save the context.
    NSError *error = nil;
    if (![self.addEditContext save:&error]){
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }

    [dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.addEditContext];
    self.addEditContext = nil;

В addControllerContextDidSave:

- (void)addControllerContextDidSave:(NSNotification*)saveNotification {
    id appDelegate = [[UIApplication sharedApplication] delegate];
    // Merging changes causes the fetched results controller to update its results
    [[appDelegate managedObjectContext] mergeChangesFromContextDidSaveNotification:saveNotification];   
}

Так что save: stuff отлично работает для нового элемента, но когда этоЭлемент устанавливается на существующиеItem и загружается снова, self.existingItem.title равен нулю.И он равен нулю с того момента, когда он представлен в контроллере представления (хотя он и не равен нулю до того, как будет представлен).Таким образом, в основном контексте, он загружает Item и его заголовок в порядке, но затем заголовок внезапно исчезает, когда он представлен в presentModalViewController: navController.

Действительно странно.Если кто-то может пролить свет на это, это будет очень ценно.

Обновление: еще одна вещь, которую стоит упомянуть, это то, что заголовок определенно сохраняется в persistentStore.Каждый раз, когда я закрываю и перезагружаю приложение, RootView показывает установленное отношение заголовка.Как только я выбираю строку, отношение становится нулевым.

1 Ответ

1 голос
/ 31 июля 2011

Ваш дизайн все излишне сложен и избыточен. Я думаю, что отношения отображаются как ноль, потому что у вас неправильный класс, назначенный для вашего свойства self.existingItem.

Во-первых, нет причин создавать другой контекст только для другого представления в том же потоке переднего плана. Просто передайте существующий контекст следующему представлению и избавьте себя от головной боли слияния с контекстом без функциональной причины.

Во-вторых, этот блок:

}else{
    self.existingItem = (Item *)[self.addEditContext objectWithID:[self.existingItem  objectID]];
}

... совершенно бессмысленно, потому что вы устанавливаете self.existingItem на себя. Вы могли бы также написать:

self.existingItem = self.existingItem;

... потому что идентификаторы объектов фиксируются в постоянном хранилище после сохранения объекта. Если объект не был сохранен, то идентификатор является временным, и другой контекст не сможет найти его в любом случае.

Наиболее вероятная причина проблемы - определение свойства existingItem. Если вы определили его как id или NSManagedObject, он не будет реагировать на селектор title и вернет ноль. Это приведет к ошибке, но вы приведете его как Item, так что компилятор думает, что он будет отвечать на все сообщения, которые может сделать объект Item.

Не используйте приведение, если вы не знаете, что заставите объект подражать другому. В противном случае вы просто создаете возможности скрывать ошибки от компилятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...