Как использовать 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 является именем свойства.