2012-07-10 2 views
11

Эта проблема сводит меня с ума. Я пытаюсь изменить viewController, когда пользователь изменяет выбранную «вкладку» сегментарного элемента управления. Я провел пару часов исследований и не смог найти ответ, который работает или делается через раскадровку.Изменение контроллера просмотра при изменении сегментированного управления

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

Большое спасибо.

+0

Вы пытаетесь заменить контроллер _view_ или _view_? Это две разные вещи. Если последнее, я бы предложил перекатить все в один контроллер представления и показать или скрыть подпункты по мере необходимости. –

+0

Ну, я действительно новичок в iOS, самая простая вещь, которая приходит мне на ум, - это изменить viewController, как это делает приложение с вкладками. Предлагаете ли вы делать разные взгляды и управлять ими с помощью одного и того же контроллера? Если да, то как я могу это сделать? Большое спасибо –

ответ

4

Я бы сказал, что это очень просто er, чтобы изменить subviews в пределах UIViewController, вы можете настроить свои подзоны в своих раскадках и подключить их с помощью IBOulets в своем контроллере, вы можете установить свойство hidden своих представлений на ДА или НЕТ в зависимости от элемента управления, который был нажат.

Теперь, если вы используете подход @Robotic Cat, который также является хорошим решением, вы можете иметь немного больше модульности в том, как работает ваше приложение, учитывая, что вам нужно будет разместить всю свою логику в одном контроллере, используя решение, которое я представил ,

+0

Мне нравится, что вы предлагали только попробовать его на xcode и выглядеть хорошо и легко реализовать. Моя единственная забота - неэффективно ли скрывать взгляды в фоновом режиме? –

+1

Я не читал ничего в тех документах разработчиков, которые идут вразрез с этим, хотя вы должны учитывать, что если вы добавите много визуальных элементов, это займет память, так что сделайте это с умом. Чтобы этого избежать, вы могли бы инициировать все, что вам нужно на лету, хотя я считаю, что накладные расходы на то, что все элементы уже настроены, минимальны. У меня есть только 4 подзаголовка с 1 или 2 текстовыми полями, например. – 8vius

+1

В одном из моих приложений для iPad у меня есть контроллер вида, который имеет 7 подзонов, которые могут быть показаны или скрыты, каждый со своим набором элементов управления. Всего около 60 просмотров и подзаголовков (ярлыки, кнопки и т. Д.). Я не замечаю замедленности или колебаний, и Profier не обнаруживает огромных всплесков в памяти или процессоре. Очевидно, что вы должны тщательно протестировать свое решение, но я сомневаюсь, что у вас возникнут проблемы. –

0

UISegmentedControl немного отличается тем, что у него нет протокола делегатов, вы должны использовать стиль «добавить цель». В вашем случае то, что вы хотите сделать, это добавить цель, которая будет уведомляться при изменении UISegmentedControl (что, скорее всего, является контроллером родительского представления), а затем эта цель может работать с переключением вкладок.

Например:

[self.mainSegmentedControl addTarget:self action:@selector(changedSegmentedControl:) forControlEvents:UIControlEventValueChanged]; 

В этом примере, код быть вызван из некоторого вида/контроллера, который имеет доступ к переменной для сегментированного управления. Мы добавляем себя, чтобы вызвать вызванный метод changedSegmentedControl :.

Тогда вы бы еще один способ, как так:

- (void)changedSegmentedControl:(id)sender 
{ 
    UISegmentedControl *ctl = sender; 
    NSLog(@"Changed value of segmented control to %d", ctl.selectedSegmentIndex); 
    // Code to change View Controller goes here 
} 

Примечание: это непроверенный код, написанный из памяти - пожалуйста, обратитесь к документации соответственно.

42

Примечание: Ответ обновляется с контроллером представления кодом оболочки для прошивки 5+ включая раздел

@interface В приложении мой, у меня есть контроллер с Control Segment в навигационной панели и нажав на вид «tabs» переключает режимы просмотра. Основная идея состоит в том, чтобы иметь массив контроллеров представлений и переключаться между ними, используя индекс сегмента (и индекс IBDction indexDidChangeForSegmentedControl.)

Пример кода (iOS 5 или новее) из моего приложения (это для 2 контроллеров представления, но это тривиально . продлено до нескольких контроллеров зрения); код немного длиннее, чем для прошивки 4, но будет держать граф объектов нетронутым Кроме того, он использует АРК:

@interface MyViewController() 
// Segmented control to switch view controllers 
@property (weak, nonatomic) IBOutlet UISegmentedControl *switchViewControllers; 

// Array of view controllers to switch between 
@property (nonatomic, copy) NSArray *allViewControllers; 

// Currently selected view controller 
@property (nonatomic, strong) UIViewController *currentViewController; 
@end 

@implementation UpdateScoreViewController 
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 
- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // Create the score view controller 
    ViewControllerA *vcA = [self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerA"]; 

    // Create the penalty view controller 
    ViewControllerB *vcB = [self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerB"]; 

    // Add A and B view controllers to the array 
    self.allViewControllers = [[NSArray alloc] initWithObjects:vcA, vcB, nil]; 

    // Ensure a view controller is loaded 
    self.switchViewControllers.selectedSegmentIndex = 0; 
    [self cycleFromViewController:self.currentViewController toViewController:[self.allViewControllers objectAtIndex:self.switchViewControllers.selectedSegmentIndex]]; 
} 

#pragma mark - View controller switching and saving 

- (void)cycleFromViewController:(UIViewController*)oldVC toViewController:(UIViewController*)newVC { 

    // Do nothing if we are attempting to swap to the same view controller 
    if (newVC == oldVC) return; 

    // Check the newVC is non-nil otherwise expect a crash: NSInvalidArgumentException 
    if (newVC) { 

     // Set the new view controller frame (in this case to be the size of the available screen bounds) 
     // Calulate any other frame animations here (e.g. for the oldVC) 
     newVC.view.frame = CGRectMake(CGRectGetMinX(self.view.bounds), CGRectGetMinY(self.view.bounds), CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds)); 

     // Check the oldVC is non-nil otherwise expect a crash: NSInvalidArgumentException 
     if (oldVC) { 

      // Start both the view controller transitions 
      [oldVC willMoveToParentViewController:nil]; 
      [self addChildViewController:newVC]; 

      // Swap the view controllers 
      // No frame animations in this code but these would go in the animations block 
      [self transitionFromViewController:oldVC 
           toViewController:newVC 
             duration:0.25 
             options:UIViewAnimationOptionLayoutSubviews 
            animations:^{} 
            completion:^(BOOL finished) { 
             // Finish both the view controller transitions 
             [oldVC removeFromParentViewController]; 
             [newVC didMoveToParentViewController:self]; 
             // Store a reference to the current controller 
             self.currentViewController = newVC; 
            }]; 

     } else { 

      // Otherwise we are adding a view controller for the first time 
      // Start the view controller transition 
      [self addChildViewController:newVC]; 

      // Add the new view controller view to the ciew hierarchy 
      [self.view addSubview:newVC.view]; 

      // End the view controller transition 
      [newVC didMoveToParentViewController:self]; 

      // Store a reference to the current controller 
      self.currentViewController = newVC; 
     } 
    } 
} 

- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl *)sender { 

    NSUInteger index = sender.selectedSegmentIndex; 

    if (UISegmentedControlNoSegment != index) { 
     UIViewController *incomingViewController = [self.allViewControllers objectAtIndex:index]; 
     [self cycleFromViewController:self.currentViewController toViewController:incomingViewController]; 
    } 

} 
@end 

Оригинальный пример (IOS 4 или выше):

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 
- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // Create the score view controller 
    AddHandScoreViewController *score = [self.storyboard instantiateViewControllerWithIdentifier:@"AddHandScore"]; 

    // Create the penalty view controller 
    AddHandPenaltyViewController *penalty = [self.storyboard instantiateViewControllerWithIdentifier:@"AddHandPenalty"]; 

    // Add Score and Penalty view controllers to the array 
    self.allViewControllers = [[NSArray alloc] initWithObjects:score, penalty, nil]; 

    // Ensure the Score controller is loaded 
    self.switchViewControllers.selectedSegmentIndex = 0; 
    [self switchToController:[self.allViewControllers objectAtIndex:self.switchViewControllers.selectedSegmentIndex]]; 
} 

#pragma mark - View controller switching and saving 

- (void)switchToController:(UIViewController *)newVC 
{ 
    if (newVC) { 
     // Do nothing if we are in the same controller 
     if (newVC == self.currentViewController) return; 

     // Remove the current controller if we are loaded and shown 
     if([self.currentViewController isViewLoaded]) [self.currentViewController.view removeFromSuperview]; 

     // Resize the new view controller 
     newVC.view.frame = CGRectMake(CGRectGetMinX(self.view.bounds), CGRectGetMinY(self.view.bounds), CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds)); 

     // Add the new controller 
     [self.view addSubview:newVC.view]; 

     // Store a reference to the current controller 
     self.currentViewController = newVC; 
    } 
} 

- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl *)sender { 

    NSUInteger index = sender.selectedSegmentIndex; 

    if (UISegmentedControlNoSegment != index) { 
     UIViewController *incomingViewController = [self.allViewControllers objectAtIndex:index]; 
     [self switchToController:incomingViewController]; 
    } 

} 
+0

Действительно приятное решение. Спасибо, что поделились этим. – Mike

+0

@Robotic Cat: Я немного смущен, почему вы устанавливаете кадр контроллера дочернего представления таким же, как контроллер родительского представления. Не содержит ли этот контроллер родительского представления UISegmentedControl? Если да, то разве контроллер дочернего представления не скроет его? – Marplesoft

+0

@Marplesoft: Обычно 'UISegmentedControl' находится в панели навигации. Очевидно, что если ваш 'UISegmentedControl' находится в вашем контроллере просмотра, вы должны установить ограничения или рамки автоопределения для правильных значений для вашего приложения. –

0

Посмотрите на этот контейнер: https://github.com/xmartlabs/XLMailBoxContainer. Это делает анимацию пользовательского интерфейса среди контроллеров представления. Эти контроллеры могут расширять UITableViewController или любой другой контроллер представления.

Надеюсь, это поможет вам!

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