Как использовать ManagedObjectContext при использовании UITabBarController
У меня есть приложение для iPhone, у которого есть MainWindow.xib с UITabBarController, который, в свою очередь, имеет UINavigationController и пользовательский подкласс UIViewController в своем массиве ViewControllers. Контроллер корневого представления для UINavigationController и настраиваемый контроллер представлений загружаются из других xib файлов.
Приложение использует основные данные, стек инициализируется в делегате приложения (согласно соглашение).
Делегат приложения добавляет UITabBarController в окно:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Configure and show the window
[window addSubview:[tabBarController view]];
[window makeKeyAndVisible];
}
Я понимаю, что мне нужно распространять указатель на ManagedObjectContext, созданный в делете приложения, но я не знаю, как это сделать (даже прочитав все хорошие комментарии по теме здесь и here):
- Я распространяю ManagedObjectContext в UITabBarController и оттуда на отдельные контроллеры представления, и если да, то как?
- Или я распространяю ManagedObjectContext непосредственно на контроллер корневого представления UINavigationController и на настраиваемый контроллер представлений и как это сделать?
Я думаю, я не очень хорошо понимаю, как работать с UITabBarController.
Ответы
Ответ 1
В идеале вы хотите передать либо NSManagedObjectContext
, NSFetchedResultsController
, либо соответствующий NSManagedObject
"вниз" в UIViewController
. Это позволяет "родителям" управлять "ребенком" и определять, что должен иметь ребенок. Это создает более слабо связанную конструкцию и позволяет вам легко перестраивать экземпляры UIViewController
по мере необходимости. Это также облегчает повторное использование UIViewController
.
В дизайне представления вкладок это ничем не отличается. Ваш AppDelegate передает NSManagedObjectContext
тому, кто отвечает за создание начальных экземпляров UIViewController
, которые входят в UITabBarController
. В свою очередь, создатель передает соответствующую информацию (NSManagedObject
, NSFetchedResultsController
и/или NSManagedObject
экземпляры) в экземпляры UIViewController
по мере их создания.
Ответ 2
Если вы хотите использовать метод инъекции зависимостей для передачи контекста управляемого объекта с помощью контроллера панели вкладок, более надежным решением будет цикл на всех контроллерах представления в applicationDidFinishLaunching
:
for (id vc in tabBarController.viewControllers) {
[vc setManagedObjectContext:self.managedObjectContext];
}
Ответ 3
Хорошо, я долго и долго смотрел образец приложения CoreDataBooks и сделал это вот так:
- Созданы IBOutlets для RootViewController (контроллер верхнего уровня UINavigationController) и MapViewController (настраиваемый контроллер представлений) в делегате приложения.
- Подключенные выходы к контроллерам вида в MainWindow.xib
-
Добавлен следующий код в applicationDidFinishLaunching
:
// pass the managed object context to the view controllers
RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
rootViewController.managedObjectContext = self.managedObjectContext;
mapViewController.managedObjectContext = self.managedObjectContext;
И теперь это работает как шарм.
Ответ 4
Я столкнулся с этой же проблемой, я поделюсь своим решением.
Сначала вам нужна ссылка на контроллер Nav на панели вкладок в файле nib, убедитесь, что вы подключили его.
IBOutlet UINavigationController *navigationController;
Затем возьмите контроллер в соответствии с рекомендациями в документах поддержки и отправьте ему managedObjectContext:
SavedTableViewController *saved = (SavedTableViewController *)[navigationController topViewController];
saved.managedObjectContext = self.managedObjectContext;
Алекс (из другого сообщения) прав: "Обычно вы должны избегать получения общих объектов из делегата приложения. Это заставляет его вести себя слишком сильно, как глобальная переменная, и у этого есть целый беспорядок связанных с ним проблем."
Ответ 5
Использование Xcode 3.2.1 и таргетинга 3.1.3 У меня были бесконечные проблемы с
rootViewController.managedObjectContext = self.managedObjectContext;
который описывает mvexcel (и что он используется во всех примерах приложений), однако используя точно такой же подход, но формулируя его как:
[rootViewController setManagedObjectContext:self.managedObjectContext];
отлично работает.
У меня также было много проблем с построением интерфейса, который не синхронизировал корректно с Xcode и поэтому не мог подключать выходы для передачи контекста. Надеюсь, следующий релиз исправит все это.
Ответ 6
Здравствуйте, я знаю, что это старый поток, но у меня также возникают проблемы с поиском лучшего способа обработки обмена MOC между TABS. - Желание Marcus Zarra по этому вопросу все еще активно. Marcus полностью скалывает, делает данные крутыми.
Это мое текущее решение в приложении didFinishLaunching:
NSArray *viewControllers = [tabBarController viewControllers];
NSManagedObjectContext *context = self.managedObjectContext;
for (id viewController in viewControllers) {
[viewController setManagedObjectContext:context];
}
Ответ 7
В моем случае у меня есть rootViewController, а затем у меня есть TabBarController, поэтому в segue, когда я готовлю tabBarController, я устанавливаю его делегат:
if ([[segue identifier]isEqualToString:@"initialTabBar"])
[(UITabBarController *)[segue destinationViewController] setDelegate:self];
} `
Я добавляю протокол к tabBarDelegate в свой RootViewController (я называл MainViewController):
@interface MainViewController ()<UITabBarControllerDelegate>
И, наконец, в методе делегата:
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
Я устанавливаю свойство, но ранее я убедился, что viewcontroller имеет правильное свойство:
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
if ([viewController respondsToSelector:@selector(managedContextObject)]) {
[viewController setValue:self.managedObjectContext forKey:@"managedContextObject"];
}
}
Таким образом, если какая-либо вкладка viewController не использует файл managedContextObject, просто я не создаю свойство в его .h
Я надеюсь, что это будет полезно.
Ответ 8
Просто пройдите через каждый viewController, проверьте, есть ли у него свойство managedObjectContext
, и затем установите его, если это так. Это самый чистый способ, который я мог бы найти для этого.
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
for (id viewController in [tabBarController viewControllers]) {
if ([viewController respondsToSelector:@selector(setManagedObjectContext:)]) {
[viewController setManagedObjectContext:self.managedObjectContext];
}
}
Ответ 9
Более прямолинейное решение состоит в том, чтобы сделать ManagedObjectContext своим публичным свойством делегировать приложение, поэтому, когда вам нужен доступ к нему, вы должны сделать следующее:
[[[UIApplication sharedApplication] delegate] sharedManagedObjectContext];
предполагая, что sharedManagedObjectContext является именем свойства.