{"id":4679,"date":"2010-11-10T10:15:43","date_gmt":"2010-11-10T09:15:43","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=4679"},"modified":"2010-11-10T10:25:55","modified_gmt":"2010-11-10T09:25:55","slug":"t080-uinavigationcontroller-for-fun-and-profit-costruiamo-un-menu-di-navigazione-personalizzato-con-uinavigationcontroller","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/t080-uinavigationcontroller-for-fun-and-profit-costruiamo-un-menu-di-navigazione-personalizzato-con-uinavigationcontroller\/","title":{"rendered":"T#080 &#8211; UINavigationController for fun and profit: Costruiamo un menu di navigazione personalizzato con UINavigationController"},"content":{"rendered":"<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/11\/t080-Using-UINavigationController-00.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/11\/t080-Using-UINavigationController-00.jpg\" alt=\"t080-Using-UINavigationController-00\" title=\"t080-Using-UINavigationController-00\" width=\"167\" height=\"150\" class=\"alignleft size-full wp-image-5084\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/11\/t080-Using-UINavigationController-00.jpg 167w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/11\/t080-Using-UINavigationController-00-150x134.jpg 150w\" sizes=\"auto, (max-width: 167px) 100vw, 167px\" \/><\/a> Una delle richieste che mi arriva pi\u00f9 spesso \u00e8 quella di gestire un&#8217;applicazione che utilizza pi\u00f9 UIViewControllers. Detto in altri termini, come costruire un menu di navigazione tra pi\u00f9 controllori resistente, riutilizzabile e privo di memory leaks. In quest&#8217;articolo vedremo come utilizzare uno degli oggetti gi\u00e0 presenti nell&#8217;UIKit per ottenere il nostro scopo.<\/p>\n<h4>Un po&#8217; di teoria<\/h4>\n<p><em>UINavigationController<\/em> \u00e8 un oggetto fornito in bundle con UIKit framework che permette di navigare gerarchicamente e con poco sforzo per il programmatore una serie di UIViewControllers che risultano arrangiati secondo uno schema padre->figlio->nipote come quello rappresentato sotto:<!--more--><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-01.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-01.jpg\" alt=\"t080-Using-UINavigationController-01\" title=\"t080-Using-UINavigationController-01\" width=\"500\" height=\"225\" class=\"aligncenter size-full wp-image-5076\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-01.jpg 500w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-01-300x135.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-01-150x67.jpg 150w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Tipicamente, il suo utilizzo \u00e8 quello di fornire una barra di navigazione in alto che permetta di effettuare le operazioni di <em>push<\/em> e <em>pop<\/em> dei <em>viewcontrollers<\/em> figli, a partire da un elemento radice. Tuttavia, come vedremo in quest&#8217;articolo, \u00e8 possibile manipolare l&#8217;oggetto <em>UINavigationController<\/em> per svolgere il suo comportamento in maniera diversa da quella standard; senza, cio\u00e8, l&#8217;ausilio di una barra di navigazione mantendendo, al contempo, tutte le sue funzionalit\u00e0 di controllore. Quello che vorremo ottenere alla fine del nostro articolo \u00e8 qualcosa di questo tipo:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-02.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-02.jpg\" alt=\"t080-Using-UINavigationController-02\" title=\"t080-Using-UINavigationController-02\" width=\"486\" height=\"349\" class=\"aligncenter size-full wp-image-5077\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-02.jpg 486w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-02-300x215.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-02-150x107.jpg 150w\" sizes=\"auto, (max-width: 486px) 100vw, 486px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Come si puo&#8217; vedere dalla figura sopra, il menu principale della nostra applicazione prevede scelte multiple che riportano l&#8217;utente a viewControllers sempre differenti. Uno per ogni task. <\/p>\n<p>Implementare questa funzionalit\u00e0 \u00e8, forse, uno dei task pi\u00f9 tediosi e soggetti a memory leaks durante la scrittura di un applicativo. Il problema \u00e8 di natura concettuale e risiede nel fatto che per gestire un insieme di viewControllers, deve esserci &#8220;qualcuno&#8221; o &#8220;qualcosa&#8221; che abbia una visione d&#8217;insieme. Qualcuno, cio\u00e8, che conosca chi \u00e8 il viewController padre, chi sono i viewControllers figli, nasconda di volta in volta il viewController che esce di scena, si occupi di rimuovere dalla memoria gli oggetti non pi\u00f9 utilizzati e molto altro.<\/p>\n<p>Uno degli errori tipici che si commette \u00e8 quello di delegare questo lavoro alla classe AppDelegate. Niente di pi\u00f9 sbagliato. Come descrive la documentazione developer e come ogni buon programmatore dovrebbe sapere, l&#8217;AppDelegate \u00e8 una classe che poco c&#8217;entra con le rappresentazioni &#8220;visive&#8221; dei nostri oggetti e dei nostri controllori. Piuttosto, essa dovrebbe occuparsi di gestire eventi di sistema ed interazione da e verso i sensori del nostro apparato. Assegnargli un compito relativo alla mera visualizzazione di viewControllers e relative views a schermo \u00e8, quantomeno, off-topics. Sarebbe come chiedere all&#8217;autista del bus 405 di fermarsi a comprare il pane, solo perch\u00e8 si trova a passare davanti ad un panificio.<\/p>\n<p>La soluzione ideale \u00e8 quella di costruire un&#8217;oggetto controllore che piloti lo scambio dei viewControllers e tenga traccia di chi \u00e8 presente e quando lo \u00e8. Un lavoro non indifferente. Apple, ci ha messo a disposizione l&#8217;oggetto UINavigationController che, come dice il nome stesso, si occupa di gestire la navigazione sequenziale di due o pi\u00f9 viewControllers. L&#8217;oggetto si occupa anche della dismissione dallo schermo e dalla memoria (se gestiti correttamente) degli oggetti non pi\u00f9 utilizzati. Inoltre, permette con estrema naturalezza di gestire un approccio Lazy-Load dei nostri controllori, in maniera da preservare lo stato della memoria del nostro dispositivo.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-03.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-03.jpg\" alt=\"t080-Using-UINavigationController-03\" title=\"t080-Using-UINavigationController-03\" width=\"500\" height=\"295\" class=\"aligncenter size-full wp-image-5078\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-03.jpg 500w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-03-300x177.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-03-150x88.jpg 150w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Il lavoro sopra sintetizzato pu\u00f2 essere riassunto nel ruolo dell&#8217;oggetto UINavigationController che, non a caso, ha anche una property per abilitare o disabilitare la sua visibilit\u00e0 a schermo, preservando al contempo le sue funzionalit\u00e0 di controllore. Andiamo a vedere come operare passo per passo, in maniera da creare il nostro primo menu personalizzato.<\/p>\n<p>Prima di tutto, creiamo un nuovo progetto e chiamiamolo &#8220;HiddenUINavigation&#8221;:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-04.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-04.jpg\" alt=\"t080-Using-UINavigationController-04\" title=\"t080-Using-UINavigationController-04\" width=\"500\" height=\"409\" class=\"aligncenter size-full wp-image-5079\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-04.jpg 500w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-04-300x245.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-04-150x122.jpg 150w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Una volta creato il progetto ricreiamo la struttura di classi seguenti:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-05.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-05.jpg\" alt=\"t080-Using-UINavigationController-05\" title=\"t080-Using-UINavigationController-05\" width=\"308\" height=\"219\" class=\"aligncenter size-full wp-image-5080\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-05.jpg 308w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-05-300x213.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-05-150x106.jpg 150w\" sizes=\"auto, (max-width: 308px) 100vw, 308px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Oltre al nostro AppDelegate, quindi, avremo una classe MainViewController ed una SecondaryViewController. Ovviamente, per ogni nuova voce del menu che andremo a costruire, dovremo creare la corrispondente classe che eridita da UIViewController. Abbiate l&#8217;accortezza di rimuovere tutti gli XIB automaticamente creati dal template wizard di XCode (MainWindow.xib, nel mio caso) e modificate il .plist di avvio in maniera che rifletta i cambiamenti apportati alle risorse.<\/p>\n<p><strong>main.m<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import <UIKit\/UIKit.h>\r\n\r\nint main(int argc, char *argv[]) {\r\n    \r\n    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];\r\n    int retVal = UIApplicationMain(argc, argv, nil, @\"HiddenUINavigationAppDelegate\");\r\n    [pool release];\r\n    return retVal;\r\n}\r\n<\/pre>\n<p>Per eliminare il file MainWindow.xib dall&#8217;elenco delle risorse necessarie all&#8217;avvio della vostra applicazione, dovrete selezionare nella cartella risorse, il file .plist con il nome del vostro progetto. Nel nostro caso HiddenUINavigation-Info.plist.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-06.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-06.jpg\" alt=\"t080-Using-UINavigationController-06\" title=\"t080-Using-UINavigationController-06\" width=\"500\" height=\"370\" class=\"aligncenter size-full wp-image-5081\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-06.jpg 500w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-06-300x222.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/10\/t080-Using-UINavigationController-06-150x111.jpg 150w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Una volta individuata la voce <strong>Main nib file base name<\/strong>, selezionate premendo il tasto destro del vostro mouse e scegliete l&#8217;opzione: CUT.<\/p>\n<p>A questo punto, la nostra applicazione \u00e8 completamente slegata dai files di risorse di interface builder. Inoltre, abbiamo inizializzato il ciclo del mainLoop con l&#8217;istanza (unica) della nostra classe AppDelegate. Non ci resta che procedere nell&#8217;implementazione di quanto sopra descritto.<\/p>\n<p>Prima di tutto aggiungiamo una variabile d&#8217;istanza al nostro AppDelegate. Questa variabile ci servir\u00e0 per referenziare l&#8217;oggetto UINavigationController. Questo sar\u00e0 l&#8217;unico oggetto gestito dal nostro AppDelegate. Modifichiamo il nostro file di interfaccia come segue:<\/p>\n<p><strong>HiddenUINavigationAppDelegate.h<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@interface HiddenUINavigationAppDelegate : NSObject <UIApplicationDelegate> {\r\n    UIWindow *window;\r\n\tUINavigationController *tmpNavController;\r\n}\r\n<\/pre>\n<p>Come si pu\u00f2 notare sono stati eliminati anche i riferimenti alla property window. Essi servono solo quando utilizziamo interface builder per la gestione della prima finestra o abbiamo esigenza di referenziare in maniera diretta l&#8217;oggetto UIWindow da fuori appDelegate. Visto che abbiamo fatto tutto programmaticamente, possiamo eliminare i metodi setter e getter per l&#8217;oggetto UIWindow. <\/p>\n<p>Spostiamoci nel file d&#8217;implementazione ed all&#8217;interno del metodo <strong>didFinishLaunchingWithOptions:<\/strong>, aggiungiamo la logica di inizializzazione della window e degli oggetti necessari a popolare la nostra applicazione.<\/p>\n<p><strong>HiddenUINavigationAppDelegate.m<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    \r\n\twindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];\r\n\t\r\n\tMainViewController *mainViewController = [[MainViewController alloc] init];\r\n\ttmpNavController = [[UINavigationController alloc] initWithRootViewController:mainViewController];\r\n\ttmpNavController.navigationBarHidden = TRUE;\r\n\t[mainViewController release];\r\n\r\n\t[window addSubview:tmpNavController.view];\r\n    [window makeKeyAndVisible];\r\n    return YES;\r\n}\r\n<\/pre>\n<p>Inizializziamo il nostro oggetto mainViewController (la classe principale responsabile del menu principale, ad esempio) assegnandolo come rootViewController all&#8217;oggetto UINavigationController appena creato. Nota come il retainCounter di mainViewController, una volta assegnato alla property dell&#8217;UINavigationController, sar\u00e0 stato incrementato di una unit\u00e0. Possiamo quindi operare un release e lasciare che sia l&#8217;UINavigationController ad occuparsene da ora in poi. Una gestione oculata e sempre attiva della memoria \u00e8 il modo migliore per evitare memory leak.<br \/>\nAggiungiamo la property view di tmpNavController come view principale della window sopra creata. A questo punto, il compito del nostro delegato \u00e8 terminato. Esso ha inizializzato correttamente la window contenitore ed i suoi oggetti principali (UINavigationController e MainViewController). L&#8217;ultimo task che dobbiamo sincerarci di compiere e&#8217; quello del rilascio di tmpNavController, ossia dell&#8217;oggetto UINavigationController. Visto che il suo compito si esaurir\u00e0 solo alla fine dell&#8217;applicazione, \u00e8 sensato rilasciarlo solo in fase di dealloc della nostra applicazione. Modifichiamo il metodo dealloc come segue:<\/p>\n<p><strong>HiddenUINavigationAppDelegate.m<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)dealloc {\r\n\t[tmpNavController release];\r\n    [window release];\r\n    [super dealloc];\r\n}\r\n<\/pre>\n<p>Passiamo adesso alla classe controllore per il menu principale: MainViewController.  Dotiamo la sua interfaccia di un oggetto UIView che utilizzeremo per renderizzare e costruire la property view. Modifichiamo il file di interfaccia come segue:<\/p>\n<p><strong>MainViewController.h<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@interface MainViewController : UIViewController {\r\n\tUIView *contentView;\r\n}\r\n<\/pre>\n<p>Spostiamoci, quindi, sul file di implementazione e costruiamo la nostra view in maniera programmatica, implementando il metodo <strong>loadView<\/strong>.<\/p>\n<p><strong>MainViewController.m<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)loadView {\r\n\tcontentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];\r\n\t[contentView setBackgroundColor:[UIColor redColor]];\r\n\r\n\tUIButton *tmpButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];\r\n\t[tmpButton setFrame:CGRectMake(0, 0, 200, 60)];\r\n\t[tmpButton setTitle:@\"pushViewController\" forState:UIControlStateNormal];\r\n\t[tmpButton addTarget:self \\\r\n\t\t\t      action:@selector(gotoSecondaryViewController) \\\r\n\t\tforControlEvents:UIControlEventTouchUpInside];\r\n\t[contentView addSubview:tmpButton];\r\n\t[tmpButton setCenter:CGPointMake(160, 240)];\r\n\tcontentView.alpha = 0.0;\r\n\tself.view = contentView;\r\n\t[contentView release];\r\n}\r\n<\/pre>\n<p>Nulla di nuovo sotto il sole. Allochiamo ed inizializziamo un oggetto UIView che assegniamo alla property view della classe controllore. Inoltre, aggiungiamo un bottone utile ai fini del nostro esempio, per muoverci agevolmente tra un viewController e l&#8217;altro. Al bottone \u00e8 associato un selettore: <strong>gotoSecondaryViewController<\/strong>.<\/p>\n<p><strong>MainViewController.m<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)gotoSecondaryViewController {\r\n\tSecondaryViewController *aController = [[SecondaryViewController alloc] init];\r\n\t[self.navigationController pushViewController:aController animated:NO];\t\r\n\t[aController release];\r\n}\r\n<\/pre>\n<p>Unica responsabilit\u00e0 del metodo sopra \u00e8 quella di allocare ed inizializzare un oggetto SecondaryViewController e pusharlo sullo stack dell&#8217;oggetto UINavigationController. Nota come ogni oggetto UIViewController eredita, implicitamente, una property navigationController che punta al nostro oggetto istanziato dall&#8217;AppDelegate.<\/p>\n<p>Analogamente, l&#8217;interfaccia della classe SecondaryViewController sar\u00e0 cos\u00ec popolata:<\/p>\n<p><strong>SecondaryViewController.h<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@interface SecondaryViewController : UIViewController {\r\n\tUIView *contentView;\r\n}\r\n<\/pre>\n<p>Il suo metodo loadView, nel file di interfaccia rifletter\u00e0 i ragionamenti sopra esposti per la classe MainViewController:<\/p>\n<p><strong>SecondaryViewController.m<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)loadView {\r\n\tcontentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];\r\n\t[contentView setBackgroundColor:[UIColor greenColor]];\r\n\tUIButton *tmpButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];\r\n\t[tmpButton setFrame:CGRectMake(0, 0, 200, 60)];\r\n\t[tmpButton setTitle:@\"pushViewController\" forState:UIControlStateNormal];\r\n\t[tmpButton addTarget:self \\\r\n\t\t\t\t  action:@selector(gotoMainViewController)\\\r\n\t    forControlEvents:UIControlEventTouchUpInside];\r\n\t[contentView addSubview:tmpButton];\r\n\t[tmpButton setCenter:CGPointMake(160, 240)];\r\n\tcontentView.alpha = 0.0;\r\n\tself.view = contentView;\r\n\t[contentView release];\r\n}\r\n<\/pre>\n<p>Questa volta, il bottone piazzato al centro della view, selezioner\u00e0 il metodo <strong>gotoMainVewController<\/strong>. L&#8217;implementazione del metodo risulta immediata:<\/p>\n<p><strong>SecondaryViewController.m<\/strong><\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n-(void)gotoMainViewController {\r\n\t[self.navigationController popViewControllerAnimated:NO];\r\n}\r\n<\/pre>\n<p>Questa volta, il selettore dovr\u00e0 semplicemente rimuovere dallo stack dell&#8217;oggetto UINavigationController l&#8217;attuale viewController, in maniera da poter ritornare al menu principale.<\/p>\n<p>A questo punto, non ci resta che compilare e provare il nostro codice. Se tutto \u00e8 stato trascritto correttamente, l&#8217;applicazione dovrebbe mostrarci un sistema di navigazione a due ViewControllers (MainViewController e SecondaryViewController). Nota come il lavoro lato AppDelegate \u00e8 molto semplice: esso si limita a dare voce e fare intervenire il controllore per i ViewControllers, inizializzando il tutto con il menu principale (MainViewController). Quest&#8217;ultimo, avr\u00e0 l&#8217;unica responsabilit\u00e0 di allocare e &#8220;pushare&#8221; sullo stack dei controllori gestiti da UINavigationController la sottovoce di menu scelta dall&#8217;utente. Nel nostro caso, SecondaryViewController.<\/p>\n<p>In questo modo, il nostro sistema di navigazione \u00e8 resistente ad errori di allocazione della memoria ed inoltre, risulta facilmente espandibile con ulteriori sottovoci. In un prossimo articolo, vedremo come dotare questo menu di un sistema di animazione per l&#8217;entrata e l&#8217;uscita dei viewcontrollers personalizzato ed altamente modulare.<\/p>\n<p>Buona programmazione a tutti!<\/p>\n<p>Costantino Pistagna<br \/>\n<a href=\"http:\/\/www.iphonesmartapps.org\/\" target=\"_blank\">iPhoneSmartApps.org<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Una delle richieste che mi arriva pi\u00f9 spesso \u00e8 quella di gestire un&#8217;applicazione che utilizza pi\u00f9 UIViewControllers&#8230;.<\/p>\n","protected":false},"author":476,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[479,478,147,63,44],"class_list":["post-4679","post","type-post","status-publish","format-standard","hentry","category-tutorial-pratici","tag-costantino-pistagna","tag-menu-iphone-app","tag-uinavigationcontroller","tag-uiview","tag-uiviewcontroller"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/4679","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/476"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=4679"}],"version-history":[{"count":9,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/4679\/revisions"}],"predecessor-version":[{"id":5090,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/4679\/revisions\/5090"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=4679"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=4679"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=4679"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}