Как использовать несколько пользовательских контроллеров представления iOS без контроллера навигации

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

- (void)changeRootViewController:(NSString *)controllerName
{
    if (controllerName == @"book") {
        rootViewController = (UIViewController *)[[BookViewController alloc] init];
        [self.window setRootViewController:rootViewController];
    } else if (controllerName == @"something_else") {
        // Use a different VC as roowViewController
    }
}

Однако то, как я это делаю, похоже, просто не может быть лучшей практикой. Я также не хочу использовать UINavigationController или UITabBarController в качестве rootViewController. Это неправильный способ сделать это, и если да, то как я должен подходить к этому по-другому?

Я думал, что это где-то обсуждалось, но (мне кажется) я погуглил, поискал похожие вопросы и т. д. Извините, если я что-то пропустил!


person GarlicFries    schedule 25.07.2011    source источник
comment
ты не хочешь использовать навигационный контроллер   -  person Amit Singh    schedule 25.07.2011
comment
что в навигационном контроллере не соответствует вашим требованиям   -  person Amit Singh    schedule 25.07.2011
comment
По нескольким причинам. Во-первых, путь через приложение не является линейным — не нужно нажимать и выталкивать контроллеры повсюду. Во-вторых, если я помещу новый контроллер представления в стек, будут ли по-прежнему использоваться ресурсы, используемые контроллерами ниже в стеке? Я не могу найти ответ на этот вопрос, но не хочу, чтобы это произошло.   -  person GarlicFries    schedule 25.07.2011
comment
Более того, я не хочу использовать UINavigationController. Я также просто хотел бы понять, как это сделать без него.   -  person GarlicFries    schedule 25.07.2011
comment
@AmitSingh причина, по которой я ищу бесплатное решение UINavigationController, заключается в том, что после входа в систему контроллер, который я хочу отправить, — это UITabBarController, но все знают, что UITabBarController нельзя отправить в UINavigationController. Любые решения?   -  person S.J    schedule 12.07.2013
comment
работает ли сравнение controllerName == @book? Мне трудно поверить.   -  person Paul de Lange    schedule 27.08.2013
comment
@ Поль де Ланж, это было - по крайней мере два года назад. Не уверен, что все еще будет...   -  person GarlicFries    schedule 27.08.2013
comment
В последнем Xcode это будет иметь неопределенное поведение предупреждения, потому что это неправильно. Вместо этого используйте -isEqual:. Я почти уверен, что это никогда не было правильно.   -  person Paul de Lange    schedule 28.08.2013
comment
Я ненавижу предупреждения и не соглашусь на подход, если это означает их проглатывание. Это действительно сработало, извини, приятель. Однако хорошо знать, что не стоит этого делать сейчас!   -  person GarlicFries    schedule 28.08.2013


Ответы (2)


Это не плохое решение. Вы в основном устанавливаете один вид в качестве корневого вида. Когда вам нужен другой UIViewController, вы устанавливаете другой. Только будьте осторожны с утечками...

  • Создайте rootViewController как свойство класса с сохранением.
  • До этого:

rootViewController = (UIViewController *)[[BookViewController alloc] init];

Добавь это:

if(rootViewController){
    self.rootViewController=nil;
}

}

Таким образом, вы отпускаете предыдущий.

Редактировать 1: Одна вещь: мое объяснение здесь основано на том факте, что вы не хотите использовать UINavigationController.

person Rui Peres    schedule 25.07.2011
comment
Спасибо. Однако есть ли более часто используемая или лучшая практика для этого? - person GarlicFries; 25.07.2011
comment
Это зависит от архитектуры вашего приложения, Бреннон. Всегда есть лучшее решение. Единственное, что мы можем сделать, это учиться каждый раз, когда мы делаем приложение, и надеяться создать лучшее в следующий раз. - person Rui Peres; 26.07.2011
comment
Хм... всегда странно принимать ответ, который в основном говорит: то, что вы уже делаете, просто прекрасно... и хотя есть лучшее решение, я не собираюсь говорить вам, что это такое... - person GarlicFries; 09.08.2011

Один отличный способ сделать это — использовать способность UIViewController iOS5+ иметь дочерние UIViewControllers (это называется сдерживанием контроллера представления). Мне, конечно, было трудно понять, как это сделать, пока я не посмотрел видео WWDC, в котором это подробно объясняется.

В двух словах, это позволяет вам создать свой собственный родительский контроллер представления, которому принадлежит ряд дочерних контроллеров представления. Этот единственный родительский контроллер представления может (и, вероятно, должен, если только вы не делаете что-то действительно причудливое :P) выступать в качестве корневого контроллера представления окна вашего приложения. Этот метод использования одного контроллера представления действует как родитель (и облегчает добавление, удаление и переход дочерних контроллеров представления) напоминает то, что делает UINavigationController (что является намерением Apple). Теперь вы можете создать свой собственный родительский контроллер вида, похожий на UINavigationController, но с совершенно другой анимацией перехода и пользовательским интерфейсом.

В качестве примера в родительском контроллере представления в viewDidLoad я добавляю первый дочерний контроллер следующим образом:

self.currentlyDisplayedChildViewController = [[TheFirstViewController alloc] init];
[self addChildViewController:self.currentlyDisplayedChildViewController];
[self.view addSubview:self.currentlyDisplayedChildViewController.view];
[self.currentlyDisplayedChildViewController didMoveToParentViewController:self];

Затем у меня будет функция для перехода к следующему дочернему контроллеру представления (ПРИМЕЧАНИЕ: эта функция принадлежит родительскому контроллеру представления — контроллеру представления, который будет действовать как ваш UINavigationController):

- (void)transitionToViewController:(UIViewController *)nextChildViewController
{
    [self addChildViewController:nextChildViewController];
    __weak TheParentViewController *me = self;
    [self transitionFromViewController:self.currentlyDisplayedChildViewController
                      toViewController:nextChildViewController
                              duration:1.0f
                               options:UIViewAnimationOptionTransitionFlipFromLeft
                            animations:nil
                            completion:^(BOOL finished)
                            {
                                [nextChildViewController didMoveToParentViewController:self];
                                [me.currentlyDisplayedChildViewController willMoveToParentViewController:nil];
                                [me.currentlyDisplayedChildViewController removeFromParentViewController];
                                me.currentlyDisplayedChildViewController = nextChildViewController;
                            }];
}

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

Я бы посоветовал взглянуть на видео WWDC2011 под названием «Реализация UIViewController Containment».

person Mr. T    schedule 15.12.2012