2013-11-07 3 views
0

Я пытаюсь получить голову над контроллерами представлений, контроллерами дочерних элементов, представлениями, контейнерами и т. Д. Я делаю простое приложение, которое будет иметь набор значков с левой стороны, что при нажатии открывается другой экран с правой стороны. Основная конструкция:UIView & UIViewController App design

enter image description here

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

enter image description here

Затем, когда изображение при нажатии на левую UIView, я должен толкать новый UIView с правой стороны? Или это должны быть UIViewControllers? Где в него входят контейнеры?

Возможно ли это сделать с помощью раскадровки, или невозможно связать кнопки, чтобы нажимать новый UIView на другую часть экрана, и поэтому мне нужно будет сделать это через код?

+0

Похоже, что вы пытаетесь сделать здесь, в основном точно так же, как то, что 'UITabBar' делает только вы хотите выступы на левой стороне вместо через дно. Это правильно? – nhgrif

+0

Да. Хотя я больше пытаюсь понять, как разные элементы должны работать вместе в хорошей практике. – Joseph

+0

Ну, причина, по которой я спросил, - это то, что вы всегда можете посмотреть, как 'UITabBar' обрабатывает содержимое каждой вкладки. Каждая вкладка - это собственный 'viewController'. Фактически вы не можете использовать 'UITabBar' для выполнения этого меню левой руки, потому что' UITabBar' идет в нижней части (и я не знаю, как это изменить), но понятия о том, как обрабатывается 'UITabBar' разные 'viewControllers' должны применяться таким же образом к настраиваемому макету, как это. – nhgrif

ответ

3

Один из вариантов заключается в том, чтобы работать с UISplitViewController, который делает большую часть этого для вас. Но вот как я буду заниматься этим.

  1. Иметь HomeViewController, которая является основной слой из-под контроля. Этот класс будет обрабатывать:

    1.1 UI для кнопок на левой

    1.2 Управление, что происходит, когда левая кнопка нажата

    1.3 Переключение из контроллеров отображения ребенка на правой

  2. На левой стороне есть UIView, назовите его navView или что-то еще, а справа - еще один UIView, называемый containerView.

    2.1 navView всегда будет виден

    2.2 containerView отвечает за отображение ваших childViewController «посмотреть

  3. Всякий раз, когда кнопка на левом нажимается удалить текущий childViewController и добавить новую ,

Here is a good tutorial on it


Edit **

В ответ на комментарий:

When you initialize the TabBar it keeps an array of the viewControllers. So your right, viewDidLoad is only called once. All you have to do to achieve that is keep an array of all your viewControllers and switch them from there. I can post code on this if you want, it seemed a bit overkill for the initial question

Здесь образец того, как я это делаю:

- (void)updateChildViewController { 

    //This is the VC that was being shown, but will be replaced by the new currentlyVisisbleViewController, we keep track of it so in the transitionFromViewController: method we have viewController to switch from. 
    UIViewController *previousVisibleViewController = self.currentlyVisibleViewController; 

    //We keep and array of both view controllers so that we only have to load them into memory once, so their viewDidLoad is only called once. 
    if (!viewControllers) { 
     viewControllers = [[NSMutableArray alloc] initWithObjects:[NSNull null], [NSNull null], nil]; 
    } 

    //If a given VC has not been loaded before we know becuase it's spot in the viewControllers array will be Null. (as seen in the line above) 
    if ([viewControllers objectAtIndex:self.displayType] == [NSNull null]) { 

     id newlyLoadedViewController; 

     //I have two display types I switch between, a map and list 
     if (self.displayType == DTMap) { 
      newlyLoadedViewController = [[MapViewController alloc] initWithNibName:@"MapViewController" bundle:nil]; 
     } 
     else if (self.displayType == DTList) { 
      newlyLoadedViewController = [[ListViewController alloc] initWithNibName:@"ListViewController" bundle:nil]; 

     } 

     //Set the object in it's location in viewControllers array 
     [viewControllers setObject:newlyLoadedViewController atIndexedSubscript:self.displayType]; 
    } 

    //Set the new currentlyVisibleViewController 
    self.currentlyVisibleViewController = [viewControllers objectAtIndex:self.displayType]; 

    //Adjust the frame to fit in the contentView (or the "container" view) 
    self.currentlyVisibleViewController.view.frame = self.contentView.frame; 

    //Make sure that it resizes on rotation automatically along with the contentView. 
    self.currentlyVisibleViewController.view.autoresizingMask = self.contentView.autoresizingMask; 

    //Let the old VC know that is going to be removed if it exist. We lazy load the UIViewControllers so on intial launch, there is only one UIViewController loaded, once we switch to another one we will have a previousVisibleViewController. 
    if (previousVisibleViewController) { 
     [previousVisibleViewController willMoveToParentViewController:nil]; 
    } 

    //Add the currentlyVisibleViewController as a childViewController 
    [self addChildViewController:self.currentlyVisibleViewController]; 

    //If there was a previousVC then we animate between them 
    if (previousVisibleViewController) { 
     [self transitionFromViewController:previousVisibleViewController 
          toViewController:self.currentlyVisibleViewController 
            duration:0.0f 
            options:UIViewAnimationOptionTransitionNone 
           animations:^{} 
           completion:^(BOOL finished) { 

            //Notify the new visible viewController than the move is done 
            [self.currentlyVisibleViewController didMoveToParentViewController:self]; 

            //Tell the old one it is no longer on the screen and has been removed. 
            [previousVisibleViewController removeFromParentViewController]; 
           }]; 
    } 

    //Otherwise it's the first time we are adding a child so we need to link the views 
    else { 

     //Add it to content view, calls willMoveToParentViewController for us. We only have to set this once. 
     [self.contentView addSubview:self.currentlyVisibleViewController.view]; 
    } 

} 
+0

Можете ли вы пояснить, что вы подразумеваете под «удалением текущего childViewController»? В настройке 'TabBar' отдельные представления имеют только свой метод' viewDidLoad', который первый раз загружается на экран. Если вы удалите представления из стека навигации, вы должны полностью перезагрузить их, и это отличается от того, как работает 'TabBar'. Есть ли способ сделать что-то похожее на то, как «TabBar», где представления не полностью удалены? – nhgrif

+0

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

+0

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

0

Я бы предложил использовать контроллер представления контейнера в качестве корня вашего макета, а затем иметь дочерний контроллер просмотра для меню левой стороны и другой контроллер представления для выбранного элемента/вкладки. Затем после выбора вы просто поменяли бы (дочерний) контроллер представления справа (то есть удалите текущий из родительского контроллера представления и добавьте новый). Хотя это может показаться несколько более сложным во-первых, это более надежный и простой в реализации более сложных сценариев, когда вы переходите к проекту.

+0

Хорошо, это звучит хорошо. Итак, в редакторе раскадровки я использую контейнеры для добавления контроллеров дочерних представлений? – Joseph

+0

Да, вы можете добавить контроллер контейнера в IB и создать встроенный segue для добавления контроллера детского представления. Однако вам необходимо обрабатывать сводные контролеры детского просмотра самостоятельно, IB на данный момент не поддерживает его. – kkodev

Смежные вопросы