2009-05-26 12 views
52

In breve: voglio avere due visualizzazioni a schermo intero, in cui posso passare dalla vista A alla vista B. So che potrei semplicemente usare un controller della barra delle linguette, ma non lo voglio. Voglio vedere come questo viene fatto a mano, per imparare cosa sta succedendo sotto il cofano.View Controller: come passare da una vista all'altra a livello di programmazione?

Ho un UIViewController che agisce come un regolatore principale:

@interface MyRootController : UIViewController { 
    IBOutlet UIView *contentView; 
} 
@property(nonatomic, retain) UIView *contentView; 

@end 

Il contentView è collegato a un UIView che ho aggiunto come visualizzazione secondaria alla "vista" del pennino. Questo ha il colore verde e lo vedo a schermo intero. Funziona bene.

Quindi, ho creato altri due controller di visualizzazione più o meno allo stesso modo. ViewControllerA e ViewControllerB. ViewControllerA ha uno sfondo blu, ViewControllerB ha uno sfondo nero. Solo per vedere quale è attivo.

Così, nella realizzazione di myRootController, faccio questo:

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

    ViewControllerA *vcA = [[ViewControllerA alloc] initWithNib]; 
    [self.contentView addSubview:vcA.view]; 

    [cvA release]; 
} 

A proposito, il metodo -initWithNib assomiglia a questo:

- (id)initWithNib { // Load the view nib 
    if (self = [super initWithNibName:@"ViewA" bundle:nil]) { 
     // do ivar initialization here, if needed 
    } 
    return self; 
} 

che funziona. Vedo la vista da ViewControllerA quando avvio l'app. Ma ora la grande domanda è: un controller di visualizzazione ha in genere tutti i seguenti metodi:

  • (vuoto) viewWillAppear: (BOOL) animato;
  • (vuoto) viewDidDisappear: (BOOL) animato;
  • (vuoto) viewDidLoad;

... e così via. Chi o cosa, o come si chiamerebbero quei metodi se faccio il "mio" modo senza un controller della barra delle linguette? Voglio dire: se alloco la classe di ViewController e la vista diventa visibile, dovrei preoccuparmi di chiamare questi metodi? Come fa a sapere che viewWillAppear, viewDidDisappear o viewDidLoad? Credo che il controller Tab Bar abbia tutta questa "intelligenza" sotto il cofano. O mi sbaglio?

AGGIORNAMENTO: l'ho provato. Se rilascio il controller di visualizzazione (ad esempio: ViewControllerA), non visualizzerò alcun messaggio di log su viewDidDisappear. Solo durante l'allocazione e l'inizializzazione di ViewControllerA, ottengo un viewDidLoad. Ma è così. Quindi tutti i segni rappresentano l'intelligenza di UITabBarController ora;) e devo capire come replicarlo, giusto?

risposta

39

Si può cominciare dal più semplice removeFromSuperview/insertSubview e aggiungere il codice a poco a poco.


//SwitchViewController.h 
#import 
@class BlueViewController; 
@class YellowViewController; 

@interface SwitchViewController : UIViewController { 
    IBOutlet BlueViewController *blueViewController; 
    IBOutlet YellowViewController *yellowViewController; 
} 
- (IBAction)switchViews:(id)sender; 
@property (nonatomic, retain) BlueViewController *blueViewController; 
@property (nonatomic, retain) YellowViewController *yellowViewController; 
@end 

//1. remove yellow view and insert blue view 
- (IBAction)switchViews:(id)sender { 
    if(self.blueViewController.view.superview == nil) 
    { 
     [yellowViewController.view removeFromSuperview]; 
     [self.view insertSubview:blueViewController.view atIndex:0]; 
    } 
} 

//2. appear=insert, disappear=remove 
if(blueViewController.view.superview == nil) 
{ 
    [blueViewController viewWillAppear:YES]; 
    [yellowViewController viewWillDisappear:YES]; 

    [yellowViewController.view removeFromSuperview]; 
    [self.view insertSubview:self.blueViewController.view atIndex:0]; 

    [yellowViewController viewDidDisappear:YES]; 
    [blueViewController viewDidAppear:YES]; 
} 

//3. now add animation 
[UIView beginAnimations:@"View Flip" context:nil]; 
[UIView setAnimationDuration:1.25]; 
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
//blue view will appear by flipping from right 
if(blueViewController.view.superview == nil) 
{ 
    [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight 
          forView:self.view cache:YES]; 

    [blueViewController viewWillAppear:YES]; 
    [yellowViewController viewWillDisappear:YES]; 

    [yellowViewController.view removeFromSuperview]; 
    [self.view insertSubview:self.blueViewController.view atIndex:0]; 

    [yellowViewController viewDidDisappear:YES]; 
    [blueViewController viewDidAppear:YES]; 
} 
[UIView commitAnimations]; 

21

Se ho capito bene, quello che stai cercando di realizzare è piuttosto semplice.

Basta aggiungere un UINavigationController sul tuo delegato applicazione e fare:

[navigationController pushView:vcA]; 

delegati saranno chiamati di conseguenza:

  • (void) viewWillAppear: (BOOL) animato;
  • (vuoto) viewDidDisappear: (BOOL) animato;
  • (vuoto) viewDidLoad;

E quando si desidera pop la vista e spingere un altro:

[navigationController popViewControllerAnimated:true]; 
[navigationController pushView:vcB]; 

Se non si desidera che il navigationController mostrando basta usare:

[navigationBar setHidden:YES]; 

Dove navigationBar è l'UINavigationBar corrispondente al tuo UINavigationController.

+0

suona bene ma non desidero alcun tipo di navigazione o barra delle schede;) Voglio solo viste nudi con un pulsante "vai a B", e sull'altro "vai su A". O c'è un modo per non avere quella barra di navigazione sopra? – Thanks

+0

Puoi sicuramente nascondere la barra di navigazione se non vuoi che venga visualizzata sullo schermo. Aggiornerò la risposta con le informazioni –

50

C'è un bell'esempio di cambio di visualizzazione nel Capitolo 6 di Beginning iPhone Development. Puoi vedere il codice sorgente qui: http://iphonedevbook.com/

SwitchViewController ha il codice per cambiare le viste a livello di codice.


- (IBAction)switchViews:(id)sender 
{ 

    if (self.yellowViewController == nil) 
    { 
     YellowViewController *yellowController = [[YellowViewController alloc] 
       initWithNibName:@"YellowView" bundle:nil]; 
     self.yellowViewController = yellowController; 
     [yellowController release]; 
    } 

    [UIView beginAnimations:@"View Flip" context:nil]; 
    [UIView setAnimationDuration:1.25]; 
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 

    UIViewController *coming = nil; 
    UIViewController *going = nil; 
    UIViewAnimationTransition transition; 

    if (self.blueViewController.view.superview == nil) 
    { 
     coming = blueViewController; 
     going = yellowViewController; 
     transition = UIViewAnimationTransitionFlipFromLeft; 
    } 
    else 
    { 
     coming = yellowViewController; 
     going = blueViewController; 
     transition = UIViewAnimationTransitionFlipFromRight; 
    } 

    [UIView setAnimationTransition: transition forView:self.view cache:YES]; 
    [coming viewWillAppear:YES]; 
    [going viewWillDisappear:YES]; 
    [going.view removeFromSuperview]; 
    [self.view insertSubview: coming.view atIndex:0]; 
    [going viewDidDisappear:YES]; 
    [coming viewDidAppear:YES]; 

    [UIView commitAnimations]; 

} 
+13

+1 per referenziare dove si ottiene l'esempio (solo ciò che @iPhoney ha dimenticato di fare). – matm

2

Questo potrebbe essere un vecchio numero, ma di recente mi sono imbattuto lo stesso problema e aveva una volta trovare qualcosa di duro che ha funzionato. Volevo passare da due controller di visualizzazione complementari, ma volevo che lo switch fosse animato (le animazioni incorporate funzionano bene) e volevo che fosse compatibile con gli storyboard, se possibile.

Per sfruttare la transizione integrata, il metododi UIView funziona magnificamente. Ma solo transizioni tra le viste, non i controller di visualizzazione.

Per la transizione tra controller di vista intera, non solo visualizzazioni, la creazione di una personalizzazione UIStoryboardSegue è la strada da percorrere. Indipendentemente dal fatto che tu usi o meno gli storyboard, questo approccio ti consente di incapsulare l'intera transizione e gestire il passaggio di informazioni rilevanti da un controller di visualizzazione a quello successivo. Coinvolge solo la sottoclasse UIStoryboardSegue e sostituisce un singolo metodo, -perform.

Per un'implementazione di riferimento, vedere RAFlipReplaceSegue, l'esatta sequenza personalizzata che ho creato utilizzando questo approccio. Come bonus, sostituisce anche il vecchio controller di visualizzazione con il nuovo se si trova in uno stack UINavigationController.

Problemi correlati