Implementazione del contenimento del contenitore - Controller del menu scorrevole

In questo tutorial, implementeremo una versione minimalista dell'interfaccia utente di Facebook / Stile del percorso. L'obiettivo sarà capire come utilizzare il contenimento del controller di visualizzazione per implementare il flusso personalizzato nella tua app.


Panoramica teorica

I controller di visualizzazione sono una parte essenziale di qualsiasi applicazione iOS, indipendentemente da quanto siano piccoli, grandi, semplici o complessi. Forniscono la "logica della colla" tra il modello dati della tua app e l'interfaccia utente.

In generale, esistono due tipi di controller di visualizzazione:

  • Controller della vista del contenuto: Questi sono responsabili della visualizzazione e della gestione del contenuto visibile.
  • Controller per container: Questi gestiscono i controller di visualizzazione del contenuto e sono responsabili della struttura e del flusso complessivi dell'app.

Un controller contenitore può avere alcuni componenti visibili, ma fondamentalmente funziona come host per i controller di visualizzazione contenuto. I controller container servono a "trafficare" l'andirivieni dei controller di visualizzazione del contenuto.

UINavigationController, UITabBarController e UIPageViewController sono esempi di controller di visualizzazione contenitori forniti con l'SDK di iOS. Considera come i tre sono diversi in termini di flussi applicativi che danno origine a. Il controller di navigazione è ottimo per un'app di tipo drill-down, in cui la selezione effettuata dall'utente in una schermata influisce sulle scelte che ha presentato nella schermata successiva. Il controller della barra delle linguette è ideale per le app con funzionalità indipendenti, consentendo un comodo comando semplicemente premendo un pulsante di tabulazione. Infine, il controller della visualizzazione di pagina presenta una metafora del libro, che consente all'utente di spostarsi avanti e indietro tra le pagine del contenuto.

La cosa fondamentale da tenere presente qui è che una vera schermata dei contenuti presentati attraverso uno di questi controller di visualizzazione contenitore deve essere gestita, sia in termini di dati da cui è derivata (il modello) che della presentazione sullo schermo (la vista), che sarebbe di nuovo il compito di un controller di visualizzazione. Ora stiamo parlando di controller di visualizzazione del contenuto. In alcune app, in particolare sull'iPad, poiché lo schermo più grande consente di visualizzare più contenuti contemporaneamente, è possibile che anche diverse visualizzazioni sullo schermo possano essere gestite autonomamente. Ciò richiede più controller di visualizzazione sullo schermo contemporaneamente. Tutto ciò implica che i controller di visualizzazione in un'app ben progettata dovrebbero essere implementati in modo gerarchico con i controller di visualizzazione del contenitore e del contenuto che riproducono i rispettivi ruoli.

Prima di iOS 5, non c'erano mezzi per dichiarare una relazione gerarchica (cioè genitore-figlio) tra due controller di vista e quindi nessun modo "corretto" di implementare un flusso di applicazioni personalizzato. Uno doveva accontentarsi dei tipi built-in, o farlo in modo casuale, che consisteva essenzialmente di incollare viste gestite da un controller di visualizzazione nella gerarchia della vista della vista gestita da un altro controller di visualizzazione. Ciò creerebbe incoerenze. Ad esempio, una vista finirebbe per essere nella gerarchia della vista di due controller senza che nessuno dei due controller riconosca l'altro, il che a volte porta a comportamenti strani. Il contenimento è stato introdotto in iOS 5 e leggermente modificato in iOS 6 e consente di formalizzare la nozione di controller di visualizzazione padre e figlio in una gerarchia. In sostanza, il corretto contenimento del controller di visualizzazione richiede che se la vista B è una sottoview (figlio) della vista A e se non sono sotto la gestione dello stesso controller di visualizzazione, allora il controllore di vista di B deve essere reso figlio di A view controller.

Potresti chiedere se ci sia un vantaggio concreto offerto dal contenimento del controller di visualizzazione oltre al vantaggio del design gerarchico di cui abbiamo discusso. La risposta è si. Tieni presente che quando un controller di visualizzazione appare sullo schermo o se ne va, potremmo aver bisogno di impostare o distruggere risorse, pulire, recuperare o salvare informazioni dal / al file system. Sappiamo tutti dei richiami all'aspetto. Dichiarando esplicitamente la relazione genitore-figlio, ci assicuriamo che il controllore genitore inoltrerà i callback ai suoi figli ogni volta che uno si accende o esce dallo schermo. Devono essere inoltrati anche i callback di rotazione. Quando l'orientamento cambia, tutti i controller di visualizzazione sullo schermo devono sapere in modo che possano adattare i loro contenuti in modo appropriato.

Cosa implica tutto ciò in termini di codice? I controller di vista hanno un NSArray proprietà chiamato childViewControllers e le nostre responsabilità includono l'aggiunta e la rimozione dei controller di vista figlio da e verso questo array nel genitore chiamando metodi appropriati. Questi metodi includono addChildViewController (chiamato il genitore) e removeFromParentViewController (chiama il bambino) quando cerchiamo di creare o distruggere la relazione genitore-figlio. Ci sono anche un paio di messaggi di notifica inviati al controller di visualizzazione figlio all'inizio e alla fine del processo di aggiunta / rimozione. Questi sono willMoveToParentViewController: e didMoveToParentViewController:, inviato con il controller genitore appropriato come argomento. L'argomento è zero, se il bambino viene rimosso. Come vedremo, uno di questi messaggi verrà inviato per noi automaticamente mentre l'altro sarà nostra responsabilità inviare. Questo dipenderà dal fatto che stiamo aggiungendo o rimuovendo il bambino. Studieremo la sequenza esatta a breve quando implementeremo le cose nel codice. Il controllore figlio può rispondere a queste notifiche implementando i metodi corrispondenti se deve fare qualcosa in preparazione di questi eventi.

Abbiamo anche bisogno di aggiungere / rimuovere le viste associate al controllore della vista figlio alla gerarchia del genitore, usando metodi come addSubview: o removeFromSuperview), compresa l'esecuzione di eventuali animazioni di accompagnamento. C'è un metodo di convenienza (-) transitionFromViewController: toViewController: Durata: opzioni: animazioni: esecuzione: ciò ci consente di semplificare il processo di scambio dei controller di visualizzazione figlio sullo schermo con animazioni. Vedremo i dettagli esatti quando scriviamo il codice - che è il prossimo!


1. Creazione di un nuovo progetto

Crea una nuova app iOS in Xcode basata su "Applicazione vuotamsgstr "Crea un app iOS con ARC abilitato VCContainmentTut.

Creare un nuovo progetto

2. Implementazione del controller Vista contenitore

Crea una nuova classe chiamata RootController. Fatelo a UIViewController sottoclasse. Assicurarsi che le caselle di controllo siano deselezionate. Questa sarà la sottoclasse del controller della vista contenitore.


Sostituisci il codice RootViewController.h con il seguente.

 #importare  @interface RootController: UIViewController // (1) - (id) initWithViewControllers: (NSArray *) viewControllers andMenuTitles: (NSArray *) titoli; // (2) @end

Il nostro controller contenitore avrà una vista tabella che funziona come il nostro menu, e toccando qualsiasi cella sostituirà il controller vista attualmente visibile da quello selezionato tramite il tocco dell'utente.

Riferendosi ai punti nel codice,

  1. Il nostro controller di root si raddoppia come delegato e origine dati del menu (cioè, la vista della tabella).
  2. Offriamo un'API estremamente semplice (per quanto riguarda il nostro utente della classe contenitore) costituita da un inizializzatore che accetta un elenco di controller di visualizzazione che il nostro controller di root deve contenere e un elenco di stringhe che rappresentano i titoli per ciascun controller di visualizzazione nel menu. Questo è così che possiamo concentrarci sulle basi. Una volta capito, puoi rendere l'API personalizzabile come preferisci.

Diamo uno sguardo avanti per vedere come sarà il nostro prodotto finito in modo da avere un'immagine mentale per associare l'implementazione con.


Aiuterà a capire che il nostro controller di visualizzazione contenitori è abbastanza simile a un controller di visualizzazione a schede. Ogni voce nel menu corrisponde a un controller di visualizzazione indipendente. La differenza tra i nostri "menu scorrevole"Il controller e il controller di tabulazione sono visivi per la maggior parte.menu scorrevole"è un po 'improprio perché è in realtà il controller di visualizzazione del contenuto che scorre per nascondere o rivelare il menu sottostante.

Passando all'implementazione, sostituire tutto il codice in RootController.m con il seguente codice.

 #define kExposedWidth 200.0 #define kMenuCellID @ "MenuCell" #import "RootController.h" @interface RootController () @property (nonatomic, strong) Menu UITableView *; @property (nonatomic, strong) NSArray * viewControllers; @property (nonatomic, strong) NSArray * menuTitles; @property (nonatomic, assign) NSInteger indexOfVisibleController; @property (nonatomic, assign) BOOL isMenuVisible; @end @implementation RootController - (id) initWithViewControllers: (NSArray *) viewControllers andMenuTitles: (NSArray *) menuTitles if (self = [super init]) NSAssert (self.viewControllers.count == self.menuTitles.count, @ "Ci deve essere uno e un solo titolo di menu corrispondente a ogni controller di visualizzazione!"); // (1) NSMutableArray * tempVCs = [NSMutableArray arrayWithCapacity: viewControllers.count]; self.menuTitles = [menuTitles copy]; for (UIViewController * vc in viewControllers) // (2) if (! [vc isMemberOfClass: [classe UINavigationController]]) [tempVCs addObject: [[UINavigationController alloc] initWithRootViewController: vc]];  else [tempVCs addObject: vc]; UIBarButtonItem * revealMenuBarButtonItem = [[UIBarButtonItem alloc]] initWithTitle: @ Stile "Menu": UIBarButtonItemStylePlain target: self action: @selector (toggleMenuVisibility :)]; // (3) UIViewController * topVC = ((UINavigationController *) tempVCs.lastObject) .topViewController; topVC.navigationItem.leftBarButtonItems = [@ [revealMenuBarButtonItem] arrayByAddingObjectsFromArray: topVC.navigationItem.leftBarButtonItems];  self.viewControllers = [tempVCs copy]; self.menu = [[UITableView alloc] init]; // (4) self.menu.delegate = self; self.menu.dataSource = self;  return self;  - (void) viewDidLoad [super viewDidLoad]; [self.menu registerClass: [UITableViewCell class] forCellReuseIdentifier: kMenuCellID]; self.menu.frame = self.view.bounds; [self.view addSubview: self.menu]; self.indexOfVisibleController = 0; UIViewController * visibleViewController = self.viewControllers [0]; visibleViewController.view.frame = [self offScreenFrame]; [self addedChildViewController: visibleViewController]; // (5) [self.view addSubview: visibleViewController.view]; // (6) self.isMenuVisible = YES; [self adjustContentFrameAccordingToMenuVisibility]; // (7) [self.viewControllers [0] didMoveToParentViewController: self]; // (8) - (void) toggleMenuVisibility: (id) sender // (9) self.isMenuVisible =! Self.isMenuVisible; [self adjustContentFrameAccordingToMenuVisibility];  - (void) adjustContentFrameAccordingToMenuVisibility // (10) UIViewController * visibleViewController = self.viewControllers [self.indexOfVisibleController]; CGSize size = visibleViewController.view.frame.size; if (self.isMenuVisible) [UIView animateWithDuration: 0.5 animazioni: ^ visibleViewController.view.frame = CGRectMake (kExposedWidth, 0, size.width, size.height); ];  else [UIView animateWithDuration: 0.5 animazioni: ^ visibleViewController.view.frame = CGRectMake (0, 0, size.width, size.height); ];  - (void) replaceVisibleViewControllerWithViewControllerAtIndex: (NSInteger) indice // (11) if (index == self.indexOfVisibleController) return; UIViewController * incomingViewController = self.viewControllers [index]; incomingViewController.view.frame = [self offScreenFrame]; UIViewController * outgoingViewController = self.viewControllers [self.indexOfVisibleController]; CGRect visibleFrame = self.view.bounds; [outgoingViewController willMoveToParentViewController: nil]; // (12) [self addedChildViewController: incomingViewController]; // (13) [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; // (14) [self transitionFromViewController: outgoingViewController // (15) toViewController: incomingViewController durata: 0,5 opzioni: 0 animazioni: ^ outgoingViewController.view.frame = [self offScreenFrame];  completamento: ^ (BOOL terminato) [UIView animateWithDuration: 0.5 animazioni: ^ [outgoingViewController.view removeFromSuperview]; [self.view addSubview: incomingViewController.view]; incomingViewController.view.frame = visibleFrame; [[UIApplication sharedApplication] endIgnoringInteractionEvents]; // (16)]; [incomingViewController didMoveToParentViewController: self]; // (17) [outgoingViewController removeFromParentViewController]; // (18) self.isMenuVisible = NO; self.indexOfVisibleController = index; ];  // (19): - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return 1;  - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section return self.menuTitles.count;  - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: kMenuCellID]; cell.textLabel.text = self.menuTitles [indexPath.row]; cella di ritorno;  - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath [self replaceVisibleViewControllerWithViewControllerAtIndex: indexPath.row];  - (CGRect) offScreenFrame return CGRectMake (self.view.bounds.size.width, 0, self.view.bounds.size.width, self.view.bounds.size.height);  @fine

Ora per una spiegazione del codice. Le parti che ho evidenziato per enfatizzare sono particolarmente rilevanti per l'implementazione del contenimento.

  1. Innanzitutto, l'inizializzatore esegue un semplice controllo per garantire che a ciascun controller di visualizzazione sia stato assegnato un titolo di menu. Non abbiamo fatto alcun tipo di controllo per garantire che ciascuno dei due array passati all'inizializzatore contenga il giusto tipo di oggetti, UIViewController e NSString tipi rispettivamente. Potresti considerare di farlo. Nota che stiamo mantenendo gli array per ognuno di questi, chiamato viewControllers, e menuTitles.
  2. Vogliamo che ci sia un pulsante che, quando viene toccato, mostra o nasconde il menu. La mia soluzione semplice su dove dovrebbe essere il pulsante era mettere ogni controller di visualizzazione che abbiamo ricevuto dall'inizializzatore all'interno di un controller di navigazione. Questo ci fornisce una barra di navigazione gratuita a cui è possibile aggiungere un pulsante, a meno che il controller di visualizzazione passato fosse già un controller di navigazione, nel qual caso non faremo nulla in più.
  3. Creiamo un elemento del pulsante della barra che attiva l'aspetto o il nascondiglio del menu facendo scorrere il controller della vista attualmente visibile. Lo aggiungiamo alla barra di navigazione spostando qualsiasi pulsante esistente sulla barra di navigazione a destra. Lo facciamo perché il controller di visualizzazione aggiunto è già un controller di navigazione con pulsanti barra preesistenti.
  4. Istanziamo il nostro menu come una vista tabella e assegniamo il controller di root stesso come delegato e origine dati.
  5. Nel viewDidLoad, dopo aver configurato e aggiunto la vista tabella del menu alla vista del nostro controller di root, introduciamo nella nostra app il primo controller di visualizzazione in viewControllers schieramento. Inviando il addChildViewController: messaggio al nostro root controller, eseguiamo la nostra prima responsabilità relativa al contenimento. Dovresti sapere che questo causa il messaggio willMoveToParentViewController: essere chiamato sul controller figlio.
  6. Si noti che abbiamo esplicitamente bisogno di aggiungere la vista del nostro controller figlio alla gerarchia della vista del genitore!
  7. Impostiamo inizialmente il menu per essere visibili e richiamiamo un metodo che regola il frame del controller della vista del contenuto visibile, tenendo conto della visibilità del menu. Analizzeremo brevemente i dettagli di questo metodo.
  8. Una volta che la vista del controller di visualizzazione figlio è comodamente nella gerarchia di visualizzazione del genitore, inviamo il messaggio didMoveToParentViewController al controller secondario aggiunto, con se stesso, l'istanza RootController, come argomento. Nel nostro controller figlio, possiamo implementare questo metodo se necessario.
  9. Un semplice metodo collegato all'azione del pulsante della nostra barra dei menu che commuta la visibilità del menu regolando la vista del controller di visualizzazione sovrapposto in modo appropriato.
  10. Come indica il nome, adjustContentFrameAccordingToMenuVisibility ci consente di regolare la cornice del controller della vista del contenuto per dirci se il menu è nascosto o meno. Se sì, si sovrappone alla superview. Altrimenti, viene spostato a destra di kExposedWidth. L'ho impostato su 200 punti.
  11. Di nuovo, come chiaramente indicato dal nome, replaceVisibleViewControllerWithViewControllerAtIndex ci consente di scambiare i controller di visualizzazione e le viste corrispondenti dalla gerarchia. Per estrarre la nostra animazione, che consiste nel far scorrere il controller della vista sostituito fuori dallo schermo verso destra e quindi introdurre il controller sostitutivo dalla stessa posizione, definiamo alcuni riquadri rettangolari.
  12. willMoveToParentViewController con zero. Una volta completato questo passaggio, questo controller di visualizzazione cesserà di ricevere l'aspetto e le richiamate di rotazione dal genitore. Questo ha senso perché non è più una parte attiva dell'app.
  13. Aggiungiamo il controller della vista in entrata come un bambino al controller di root, simile a quello che abbiamo fatto all'inizio.
  14. Iniziamo a ignorare gli eventi di interazione dell'utente per consentire al nostro controller di visualizzazione di passare senza intoppi.
  15. Questo metodo di praticità ci consente di animare la rimozione del controller in uscita e l'arrivo di quello in entrata mentre eseguiamo la sequenza richiesta di eventi coinvolti nel processo di aggiunta e rimozione del controller della visualizzazione figlio. Animiamo la vista del VC in uscita per far scorrere lo schermo verso destra, e dopo che l'animazione è completata, la rimuoviamo dalla gerarchia della vista. Animiamo quindi il controller della vista in entrata per farlo scorrere dallo stesso posto fuori dallo schermo e occupare il posto precedentemente occupato dalla vista del controller in uscita.
  16. Permettiamo alla nostra app di accettare eventi di interazione in entrata, dal momento che il nostro controller di visualizzazione è stato completato.
  17. Notifichiamo al controller della vista in entrata che è stato spostato sul controller del contenitore inviandolo didMoveToParentViewController messaggio con se stesso come argomento.
  18. Rimuoviamo il controller in uscita dal controller del contenitore inviandolo removeFromParentViewController Messaggio. Dovresti saperlo didMoveToParentViewController: con zero come argomento viene inviato per te.
  19. Implementiamo i metodi del delegato e della sorgente di dati della vista tabella del menu, che sono piuttosto semplici. Ciò include l'attivazione del passaggio di swapping del controller della vista (11) quando la cella di un nuovo elemento viene toccata nel menu tramite -tableView: didSelectRowAtIndexPath: metodo.

Potresti aver trovato la sequenza di chiamate relative al contenimento del controller un po 'confusa. Aiuta a riassumere.

    Quando si aggiunge un controller di visualizzazione figlio a un genitore:
  • Chiamata addChildViewController: sul genitore con il bambino come argomento. Questo causa il messaggio willMoveToParentViewController: da inviare al bambino con il genitore come argomento.
  • Aggiungi la vista del bambino come sottoview della vista del genitore.
  • Chiamare esplicitamente didMoveToParentViewController: sul bambino con il genitore come argomento.
    Quando si rimuove un controller di visualizzazione figlio dal relativo genitore:
  • Chiamata willMoveToParentViewController: sul bambino con zero come argomento.
  • Rimuovi la vista del bambino dalla sua superview.
  • Inviare removeFromParentViewController al bambino. Causa il messaggio didMoveToParentViewController con zero come argomento da inviare al bambino a tuo nome.

3. Test

Proviamo i diversi tipi di controller di visualizzazione aggiunti al nostro controller di root! Crea una nuova sottoclasse di UIViewController chiamato ViewController, mantenendo deselezionate le opzioni.

Sostituisci il codice in ViewController.m con il seguente codice.

 #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void) willMoveToParentViewController: (UIViewController *) parent NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto classe] ), self, NSStringFromSelector (_cmd));  - (void) didMoveToParentViewController: (UIViewController *) parent NSLog (@ "% @ (% p) -% @", NSStringFromClass ([self class]), self, NSStringFromSelector (_cmd));  - (void) viewWillAppear: (BOOL) animato [super viewWillAppear: animated]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto classe]), self, NSStringFromSelector (_cmd));  - (void) viewDidAppear: (BOOL) animato [super viewDidAppear: animato]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto classe]), self, NSStringFromSelector (_cmd));  - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration [super willRotateToInterfaceOrientation: toInterfaceOrientation duration: duration]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto classe]), self, NSStringFromSelector (_cmd));  - (void) haRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation [super didRotateFromInterfaceOrientation: fromInterfaceOrientation]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto classe]), self, NSStringFromSelector (_cmd));  @fine

Non c'è nulla di speciale nel nostro controller di visualizzazione, tranne che abbiamo sovrascritto i vari callback in modo da poterli registrare ogni volta che il nostro ViewController l'istanza diventa un figlio per il nostro controller di root e si verifica un evento di comparsa o di rotazione.

In tutto il codice precedente, _cmd si riferisce al selettore corrispondente al metodo in cui si trova la nostra esecuzione. NSStringFromSelector () lo converte in una stringa. Questo è un modo semplice e veloce per ottenere il nome del metodo corrente senza doverlo digitare manualmente.

Lanciamo un controller di navigazione e un controller di tabulazione nel mix. Questa volta useremo Storyboard.

Crea un nuovo file e sotto iOS> Interfaccia utente, scegliere storyboard. Imposta la famiglia di dispositivi su i phone, e nominalo NavStoryBoard.


Dal libreria di oggetti, trascinare e rilasciare a Controller di navigazione oggetto nella tela. Trascina e rilascia a elemento pulsante bar nella parte sinistra della barra di navigazione in controller di visualizzazione tabella designato come "Root View ControllerMsgstr "Questo contiene la vista tabella nell'area di disegno. Assegna un nome qualsiasi.SinistraIl suo scopo è quello di verificare il codice che abbiamo scritto per fare in modo che il pulsante nascondi / rivela della barra dei menu sia posizionato come il pulsante più a sinistra sulla barra di navigazione, spingendo a destra qualsiasi pulsante già presente. Visualizza controller istanza e posizionarlo a destra del controller intitolato "Root View Controller"nella tela.

Clicca dove dice "Vista tabella"al centro del secondo controller e nel ispettore di attributi cambia il contenuto da "Prototipo dinamico" a "Celle statiche".

Modifica del tipo di contenuto della cella da dinamico a statico

Ciò causerà la visualizzazione di tre celle di visualizzazione tabella statiche nel builder dell'interfaccia. Elimina tutte tranne una di queste celle di visualizzazione tabella e mentre tieni premuto Controllo, fare clic e trascinare dalla cella rimanente al controller della vista all'estrema destra e rilasciare. Seleziona "Spingere" sotto Segmento di selezione. Tutto ciò fa sì che segua il controller della vista a destra quando tocchi la cella solitaria dalla vista tabella. Se vuoi, puoi lasciare un UILabel sulla cella della tabella per dargli del testo. Lo storyboard dovrebbe essere simile alla foto qui sotto.

NavStoryBoard

Infine, aggiungiamo un controller della barra delle linguette. Proprio come hai fatto in precedenza, crea un storyboard file e chiamalo TabStoryBoard. Trascina e rilascia a controller della barra delle linguette oggetto dal libreria di oggetti nella tela. Viene preconfigurato con due schede e, se lo desideri, puoi cambiare il colore di sfondo dei due controller a schede, facendo clic sulla vista corrispondente a entrambi i controller di visualizzazione e modificando il "sfondo"opzione nel Ispettore degli attributi. In questo modo, è possibile verificare che la selezione del controller di visualizzazione tramite la scheda funzioni correttamente.

Il tuo tabellone dovrebbe assomigliare a questo.

4. Configurazione del delegato dell'app

Ora è il momento di impostare tutto in AppDelegate.

Sostituisci il codice in AppDelegate.m con il seguente codice.

 #import "AppDelegate.h" #import "RootController.h" #import "ViewController.h" @implementation AppDelegate - (BOOL) application: (applicazione UIApplication *) didFinishLaunchingWithOptions: (NSDictionary *) launchOptions self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bound]]; UIStoryboard * tabStoryBoard = [UIStoryboard StoryboardWithName: @ "TabStoryboard" bundle: nil]; UIStoryboard * navStoryBoard = [UIStoryboard storyboardWithName: @ "NavStoryboard" bundle: nil]; UINavigationController * navController = [navStoryBoard instantiateViewControllerWithIdentifier: @ "Nav Controller"]; UITabBarController * tabController = [tabStoryBoard instantiateViewControllerWithIdentifier: @ "Tab Controller"]; ViewController * redVC, * greenVC; redVC = [[ViewController alloc] init]; greenVC = [[ViewController alloc] init]; redVC.view.backgroundColor = [UIColor redColor]; greenVC.view.backgroundColor = [UIColor greenColor]; RootController * menuController = [[RootController alloc] initWithViewControllers: @ [tabController, redVC, greenVC, navController] andMenuTitles: @ [@ "Tab", @ "Red", @ "Green", @ "Nav"]]; self.window.rootViewController = menuController; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; 

Tutto ciò che abbiamo fatto è stato creare istanze di ViewController e istanziare la navigazione e il controller delle schede dai due storyboard. Li abbiamo passati in fila al nostro RootControllerl'istanza Questo è il controller contenitore che abbiamo implementato all'inizio. Lo abbiamo fatto insieme a una serie di stringhe per nominare i controller della vista nel menu. Ora definiremo semplicemente la nostra istanza Root Controller inizializzata come quella della finestra RootViewController proprietà.

Costruisci ed esegui l'app. Hai appena implementato il contenimento dei container! Toccare le varie celle della tabella nel menu per sostituire la diapositiva visibile con quella nuova che scorre da destra. Si noti come, per l'istanza del controller di navigazione (denominata "NAVC"nel menu), il"Sinistra"il pulsante si è spostato di un posto a destra e il pulsante della barra dei menu ha assunto la posizione più a sinistra. Puoi cambiare l'orientamento in orizzontale e verificare che tutto appaia corretto.

Schermate del simulatore

Conclusione

In questo tutorial introduttivo, abbiamo esaminato il modo in cui il contenimento del controller di visualizzazione è implementato in iOS 6. Abbiamo sviluppato una versione semplice di un'interfaccia per app personalizzata che ha guadagnato molta popolarità e viene spesso vista in app molto utilizzate come Facebook e Path. La nostra implementazione è stata la più semplice possibile, quindi siamo stati in grado di sezionarlo facilmente e ottenere le basi giuste. Esistono molte sofisticate implementazioni open source di questo tipo di controller che puoi scaricare e studiare. Si apre una rapida ricerca su Google JASidePAnels e SWRevealViewController, tra gli altri.

Ecco alcune idee su cui puoi lavorare.

  • Rendi l'implementazione più flessibile e l'API più personalizzabile.
  • Rendi l'interfaccia più carina. È possibile personalizzare l'aspetto della cella della vista tabella o lasciare che la vista del controller della vista proietti un'ombra sul menu per conferire profondità all'interfaccia.
  • Rendere l'interfaccia adatta meglio all'orientamento. Ricorda che i tuoi controller di visualizzazione figlio riceveranno notifiche di rotazione, quindi è da lì che inizi!
  • Implementare il riconoscimento dei gesti in modo che sia possibile trascinare un controller di visualizzazione a sinistra e a destra sullo schermo come alternativa al clic sul pulsante del menu.
  • Progetta e sviluppa un flusso di app completamente nuovo e innovativo e realizza l'interfaccia utente in codice. È probabile che avrai bisogno di utilizzare il contenimento del controller di visualizzazione!

Una co