Работа с одним и тем же NSManagedObjectContext на нескольких вкладках - PullRequest
0 голосов
/ 08 апреля 2011

У меня есть контроллер панели вкладок с различными контроллерами представления, использующими один и тот же контекст управляемого объекта, настроенный следующим образом:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

RootViewController *rootVC = [[RootViewController alloc] initWithStyle:UITableViewStyleGrouped];
rootViewController.managedObjectContext = self.managedObjectContext;
UINavigationController *rootNavCon = [[UINavigationController alloc] initWithRootViewController:rootVC];
[rootVC release];

SettingsTableViewController *settingsVC = [[SettingsTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
settingsVC.managedObjectContext = self.managedObjectContext;
UINavigationController *settingsNavCon = [[UINavigationController alloc] initWithRootViewController:settingsVC];
[settingsVC release];

tabBarController = [[UITabBarController alloc] init];
NSArray *controllers = [NSArray arrayWithObjects:rootNavCon, settingsNavCon, nil];
tabBarController.viewControllers = controllers;

[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];

return YES;

}

Идея похожа на рецептыПример кода, если есть еще одна вкладка под названием «Настройки», которая предлагает опцию для управления объектами категории.Проблема заключается в том, что если вы перейдете к представлению, в котором пользователь может выбрать категорию, а затем перейдите на вкладку настроек и удалите, добавите или измените категорию, при возврате на вкладку «Рецепты» изменения не будут отражены немедленно.Таким образом, выбор удаленной категории вызовет исключение.

Как лучше всего с этим справиться?Я думал о настройке NSNotification для оповещения о представлениях всякий раз, когда произошло важное изменение, но я не был уверен, есть ли лучший способ сделать это, например, запросить [managedObjectContext hasChanges] при появлении представления.(Хотя это не сработает, если контекст уже был сохранен.)

Ответы [ 2 ]

2 голосов
/ 08 апреля 2011

Там действительно нет ответа на ваш вопрос, кроме «Это дизайнерское решение, которое вы должны принять». Тщательно продумайте свои варианты использования и сделайте соответствующую вещь.

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

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

Мой совет - создать несколько контекстов управляемых объектов для каждого рабочего процесса, которые могут изменять данные. Тогда я бы предположил, что вы можете использовать один контекст управляемого объекта для всех экранов только для чтения. Другой альтернативой может быть использование контекста управляемого объекта, выделенного для каждой вкладки. Это будет гарантировать, что изменения будут сделаны изолированно и распространяться по мере необходимости, но вам придется зарегистрировать контексты для получения уведомлений об изменениях, а затем объединить эти изменения соответствующим образом.

Чтобы проиллюстрировать, представьте, что на следующей диаграмме изображен iPhone с несколькими вкладками, и каждый соответствующий контроллер выполняет определенные действия в заданные моменты времени.

Tab A:  Controller M |---------------         ,------->
        Controller N                 `-------+
                                             | via NSNotificationCenter
                                             v
Tab B:  Controller O |-----------------------+-------->

Контроллеры M и O являются членами массива viewController в контроллере панели вкладок. Пользователь начинает с Вкладка A осматривается, затем переходит к Вкладка B . Затем пользователь возвращается к Tab A и помещает Controller N в стек навигации Tab A и вносит некоторые изменения (например, в пример удаления вашей категории). Удаление может или не может быть распространено на вкладку B. Вы можете сделать это, имея два контекста управляемого объекта, где один прослушивает уведомления об изменениях, которые другой транслировал через менеджер уведомлений.

Определение этих вариантов использования, вероятно, является трудной частью, потому что я уверен, что вы понимаете, как работает NSManagedObjectContext в целом (если нет, вам следует потратить некоторое время на его более полное понимание). Как вы можете видеть из этой простой диаграммы, для чрезвычайно простого варианта использования он вводит другое измерение сложности. Поэтому я хочу сказать, что вы должны планировать заранее, если вам не нужно разбирать и восстанавливать части вашего кода по мере его развития.

1 голос
/ 08 апреля 2011

Если вы хотите, чтобы изменения контекста вашего управляемого объекта распространялись на ваш интерфейс автоматически, и вы используете табличные представления (или даже пользовательские представления), вы можете использовать NSFetchedResultsController . Этот класс отслеживает контекст на предмет изменений и запускает его методы делегата, позволяя вам перезагружать ваши представления только при необходимости.

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