2012-07-10 12 views
11

Questo problema mi sta facendo impazzire. Sto cercando di cambiare il viewController quando l'utente cambia la "scheda" selezionata del controllo segmentato. Ho passato un paio d'ore a cercare e non sono stato in grado di trovare una risposta che funzioni o sia fatta attraverso lo storyboard.Modifica del controller della vista quando il controllo Segmentato cambia

Mi dà davvero fastidio dal momento che impostare un'applicazione di tabulazione è semplice, ma provare a utilizzare il controllo segmentato come l'applicazione di tabulazione non funziona. So già come rilevare quale indice è selezionato nel controllo segmentato. Come posso raggiungere questo obiettivo?

Grazie mille.

+0

Stai cercando di sostituire un _view_ o un _view controller_? Sono due cose diverse. In quest'ultimo caso, suggerirei di spostare tutto in un unico controller di visualizzazione e mostrare o nascondere le subview come sono necessarie. –

+0

Beh, sono davvero nuovo in iOS, la cosa più semplice che mi viene in mente è cambiare il viewController proprio come fa un'applicazione a schede. Suggerite di creare varie viste e gestirle con lo stesso controller di visualizzazione? Se è così, come posso farlo? Grazie mille –

risposta

4

Direi che è molto sim Per modificare le visualizzazioni secondarie all'interno di un UIViewController, è possibile impostare le proprie visualizzazioni secondarie negli storyboard e collegarle con IBOulets nel controller in cui è possibile impostare la proprietà hidden delle viste su SÌ o NO a seconda del controllo su cui è stato fatto clic.

Ora, se si utilizza l'approccio di @Robotic Cat, che è anche una buona soluzione, si può avere un po 'più di modularità nel modo in cui funziona l'app, considerando che dovresti mettere tutta la tua logica in un controller usando la soluzione che ho presentato .

+0

Mi piace il tuo suggerimento appena provato su xcode e sembra buono e facile da implementare. La mia unica preoccupazione è che sia inefficiente avere viste nascoste sullo sfondo? –

+1

Non ho letto nulla nei documenti dello sviluppatore che va contro questo, anche se devi considerare che se aggiungi molti elementi visivi occuperà memoria, quindi fallo saggiamente. Per evitare ciò, è possibile instillare tutto ciò che serve al volo, anche se credo che il sovraccarico di avere tutti gli elementi già impostati sia minimo. Ho solo 4 sottoview ciascuna con 1 o 2 campi di testo, per esempio. – 8vius

+1

In una delle mie app per iPad, ho un controller di visualizzazione che ha 7 sottomenu che potrebbero essere mostrate o nascoste, ciascuna con il proprio set di controlli. In tutto, ci sono circa 60 visualizzazioni e sottovie (etichette, pulsanti, ecc.). Non noto alcuna lentezza o esitazione e Profier non rivela alcun picco nella memoria o nella CPU. Ovviamente, dovresti testare accuratamente la tua soluzione, ma dubito che avrai un problema. –

0

UISegmentedControl è un po 'diverso in quanto non ha un protocollo delegato, è necessario utilizzare lo stile "aggiungi target". Nel tuo caso, ciò che vuoi fare è aggiungere un target da notificare quando cambia UISegmentedControl (che è probabilmente il controllore della vista genitore), e quindi quella destinazione può gestire il cambio di tabulazione.

Ad esempio:

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

In questo esempio, il codice viene richiamato da qualche vista/controllore che ha accesso alla variabile per il controllo segmentato. Aggiungiamo noi stessi per ottenere il changeSegmentedControl: metodo invocato.

allora si avrebbe un altro metodo in questo modo:

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

Nota: questo è il codice non testato scritta dalla memoria - si prega di consultare la documentazione di conseguenza.

42

NOTA: risposta aggiornato con View Controller codice di contenimento per iOS 5+ compreso sezione @interface

In un'applicazione di mio, ho un controller di vista con un controllo dei segmenti nella barra di navigazione e facendo clic sul gli interruttori "tabs" visualizzano i controller. L'idea di base è disporre di una serie di controller di visualizzazione e passare da essi utilizzando l'indice di segmento (e indexDidChangeForSegmentedControl IBAction.

Codice di esempio (iOS 5 o successivo) dalla mia app (questo è per 2 controller di vista ma è banalmente . esteso a più controller di vista), il codice è leggermente più lungo per iOS 4 ma manterrà intatto il grafico oggetto Inoltre, esso utilizza ARC: esempio

@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 

originale (iOS 4 o prima):

// 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

Soluzione davvero bella. Grazie per aver condiviso questo. – Mike

+0

@Robotic Cat: Sono un po 'confuso perché si imposta la cornice del controller di visualizzazione figlio per essere uguale al controller di visualizzazione genitore. Questo controller di visualizzazione principale non contiene UISegmentedControl? In tal caso, il controllore del bambino non lo oscurerebbe? – Marplesoft

+0

@Marplesoft: in genere 'UISegmentedControl' è nella barra di navigazione. Ovviamente, se il tuo 'UISegmentedControl' è nel tuo controller di visualizzazione, dovresti impostare i vincoli o il frame di autolayout sui valori corretti per la tua app. –

0

Dai un'occhiata a questo contenitore: https://github.com/xmartlabs/XLMailBoxContainer. Rende l'animazione dell'interfaccia utente tra i controller di visualizzazione. Questi controller di visualizzazione possono estendere UITableViewController o qualsiasi altro controller di visualizzazione.

Spero che questo ti aiuti!

Problemi correlati