Punerea în aplicare a Container Containment - Controlul glisant al meniului

În acest tutorial, vom implementa o versiune minimalistă a interfeței cu stilul Facebook / Cale. Obiectivul va fi să înțelegeți cum să utilizați dispozitivul de control al vizualizării pentru a implementa fluxul personalizat în aplicația dvs..


Prezentare generală teoretică

Vizualizarea controlorilor reprezintă o parte esențială a oricărei aplicații iOS, indiferent cât de mică, mare, simplă sau complexă. Ele oferă "logica lipiciului" între modelul de date al aplicației dvs. și interfața cu utilizatorul.

În general, există două tipuri de controlori de vizualizare:

  • Controlerele de vizualizare a conținutului: Acestea sunt responsabile pentru afișarea și gestionarea conținutului vizibil.
  • Controlere pentru containere: Acestea gestionează controlorii de vizualizare a conținutului și sunt responsabili pentru structura și fluxul general al aplicației.

Un controler de container poate avea o componentă vizibilă proprie, dar în principiu funcționează ca o gazdă pentru controlorii de vizualizare a conținutului. Controlerele de containere servesc la "traficul" intrarilor și ieșirilor controlorilor de vizualizare a conținutului.

UINavigationController, UITabBarController și UIPageViewController sunt exemple de controale de vizualizare a containerelor livrate împreună cu SDK-ul iOS. Luați în considerare modul în care cele trei sunt diferite în ceea ce privește fluxurile de aplicare pe care le generează. Controlerul de navigare este excelent pentru o aplicație tip drill-down, în care selecția pe care o face utilizatorul într-un singur ecran afectează opțiunile pe care le-a prezentat în următorul ecran. Controlerul bara de tab-uri este excelent pentru aplicații cu bucăți independente de funcționalitate, permițând o comutare convenabilă prin simpla apăsare a unui buton de file. În cele din urmă, controlerul de vizualizare a paginii prezintă o metaforă a cărții, permițând utilizatorului să se întoarcă înainte și înapoi între paginile de conținut.

Lucrul cheie pe care trebuie să-l rețineți este că un ecran real de conținut prezentat prin oricare dintre aceste controlere de vizualizare a containerelor trebuie să fie gestionat, atât din punct de vedere al datelor derivate din (model), cât și din prezentarea pe ecran (vizualizarea), care ar fi din nou funcția unui controlor de vizualizare. Acum vorbim despre controlori de vizualizare a conținutului. În unele aplicații, în special pe iPad, deoarece ecranul său mai mare permite afișarea simultană a mai multor conținuturi, este posibil ca și alte vizualizări pe ecran să fie gestionate independent. Acest lucru necesită controale multiple de vizualizare pe ecran simultan. Toate acestea implică faptul că controlorii de vizualizare dintr-o aplicație bine concepută ar trebui să fie implementată într-o manieră ierarhică, atât cu controlori de vizualizare a containerelor cât și a conținutului, care își pot juca rolurile respective.

Înainte de iOS 5, nu au existat mijloace de declarare a unei relații ierarhice (adică a părinte-copil) între două controale de vizualizare și, prin urmare, nu există un mod "potrivit" de a implementa un flux de aplicații personalizat. Unul a trebuit fie să se ocupe cu tipurile încorporate, fie să o facă într-un mod întâmplător, care în esență constau în lipirea vederilor gestionate de un controler de vizualizare în ierarhia de vizualizare a vederii gestionate de un alt controler de vizualizare. Acest lucru ar crea inconsecvențe. De exemplu, o viziune s-ar sfârși prin a fi în ierarhia vizuală a doi controlori, fără ca vreunul dintre acești controlori să recunoască celălalt, ceea ce uneori conduce la un comportament ciudat. Restrângerea a fost introdusă în iOS 5 și îmbunătățită ușor în iOS 6 și permite notiunea de control al vizualizării părintelui și copilului într-o ierarhie care să fie formalizată. În esență, controlarea corectă a controlerului de vizualizare cere ca dacă vizualizarea B este un subiectiv (copil) de vizualizare A și dacă nu este sub conducerea aceluiași controler de vizualizare, atunci controlerul de vedere al lui B trebuie să fie făcut din copilul controlerului vizual al lui A.

S-ar putea să întrebați dacă există vreun avantaj concret oferit de controlerul de vizualizare, în afară de avantajul designului ierarhic pe care l-am discutat. Raspunsul este da. Rețineți că atunci când un controler de vizualizare se afișează pe ecran sau se îndepărtează, este posibil să fie nevoie să configurați sau să rupeți resursele, să curățați, să preluați sau să salvați informații din / în sistemul de fișiere. Știm cu toții despre apelurile de apel. Prin declararea explicită a relației părinte-copil, ne asigurăm că parinterul va transmite apeluri către copiii săi ori de câte ori se pornește sau se stinge ecranul. Comenzile de rotație trebuie redirecționate de asemenea. Atunci când orientarea se schimbă, toți controlorii de vizualizare de pe ecran trebuie să cunoască, astfel încât să își poată ajusta în mod corespunzător conținutul.

Ce implică toate acestea, în termeni de cod? Vizualizați controlerele au un NSArray proprietatea numită childViewControllers și responsabilitățile noastre includ adăugarea și eliminarea controlorilor de vizualizare a copiilor de la și de la acest matrice în părinte, prin apelarea metodelor adecvate. Aceste metode includ addChildViewController (numit de părinte) și removeFromParentViewController (apelat la copil) atunci când căutăm să facem sau să rupem relația părinte-copil. Există, de asemenea, câteva mesaje de notificare trimise la controlerul vizualizare copil la începutul și la sfârșitul procesului de adăugare / eliminare. Acestea sunt willMoveToParentViewController: și didMoveToParentViewController:, trimis împreună cu controlerul părinte corespunzător ca argument. Argumentul este zero, dacă copilul este înlăturat. După cum vom vedea, unul dintre aceste mesaje va fi trimis pentru noi în mod automat, în timp ce celălalt va fi responsabilitatea noastră de a trimite. Acest lucru va depinde de adăugarea sau eliminarea copilului. Vom studia secvența exactă când vom implementa lucrurile în cod. Controlorul copilului poate răspunde la aceste notificări prin implementarea metodelor corespunzătoare dacă trebuie să facă ceva în pregătirea acestor evenimente.

De asemenea, este necesar să adăugăm / eliminăm vizualizările asociate controlerului de vizualizare a copiilor în ierarhia părintelui, folosind metode precum addSubview: sau removeFromSuperview), inclusiv realizarea animațiilor însoțitoare. Există o metodă convenabilă (-) transitionFromViewController: toViewController: Durata: opțiuni: animații: finalizare: care ne permite să optimizăm procesul de schimbare a controlorilor de vizualizare a copiilor pe ecran cu animații. Vom analiza exact detaliile când vom scrie codul - care este următorul!


1. Crearea unui nou proiect

Creați o nouă aplicație iOS în Xcode bazată pe "Cerere goală"șablon. Faceți-i un App iOS cu ARC activat VCContainmentTut.

Crearea unui nou proiect

2. Implementarea controlerului de vizualizare a containerelor

Creați o nouă clasă numită RootController. Fa-o a UIViewController subclasă. Asigurați-vă că toate casetele de selectare sunt deselectate. Aceasta va fi subclasa controlerului nostru de vizualizare a containerelor.


Înlocuiți codul în RootViewController.h cu următoarele.

 #import  @ interfață RootController: UIViewController // (1) - (id) initWithViewControllers: (NSArray *) vizualizareControllers și MenuTitles: (NSArray *) titluri; // (2) @end

Controlerul nostru pentru containere va avea o vizualizare de tabel care funcționează ca meniu și atingerea oricărei celule va înlocui controlerul de vizualizare vizibil în prezent cu cel selectat prin apăsarea utilizatorului.

Referindu-se la punctele din cod,

  1. Controlerul rădăcină se dublează ca delegat (și anume, vizualizarea tabelului) delegat și sursă de date.
  2. Oferim un API extrem de simplu (în ceea ce privește utilizatorul nostru de clasă de contacte) care constă dintr-un inițializator care ia o listă a controlorilor de vizualizare pe care regulatorul nostru de bază trebuie să o conțină și o listă a șirurilor care reprezintă titlurile pentru fiecare controler de vizualizare din meniul. Acest lucru este astfel încât ne putem concentra pe elementele de bază. După ce le înțelegeți, puteți face ca API să fie personalizabil după cum doriți.

Să aruncăm o privire înainte pentru a vedea cum va arăta produsul nostru finit, astfel încât să aveți o imagine mentală pentru a asocia implementarea.


Acesta va ajuta să realizăm că controlerul nostru de vizualizare a containerelor este destul de similar cu un controler vizualizare tab. Fiecare element din meniu corespunde unui controler vizual independent. Diferența dintre "meniul glisant"controlerul și controlerul tab-ului sunt vizuale pentru cea mai mare parte.Fraza"meniul glisant"este un pic de nume greșit, deoarece este de fapt controlerul de vizualizare a conținutului care alunecă pentru a ascunde sau a dezvălui meniul dedesubt.

Continuând implementarea, înlocuiți tot codul în RootController.m cu următorul cod.

 #define kExposedWidth 200.0 #define kMenuCellID @ "MenuCell" #import "RootController.h" @interface RootController () @property (nonatomic, puternic) meniu UITableView *; @property (nonatomic, puternic) NSArray * viewControllers; @property (nonatomic, strong) NSArray * meniuTitle; @property (nonatomic, atribuire) NSInteger indexOfVisibleController; @property (nonatomic, atribuire) BOOL esteMenuVisible; @end @implementation RootController - (id) initWithViewControllers: (NSArray *) vizualizareControllers șiMenuTitles: (NSArray *) menuTitles if (self = [super init]) NSAssert (self.menuTitles.count, "Trebuie să existe un singur titlu de meniu corespunzător fiecărui controler de vizualizare!"); // (1) NSMutableArray * tempVCs = [NSMutableArray arrayWithCapacity: viewControllers.count]; auto.menuTitles = [copyTitles copy]; pentru (UIViewController * vc în ViewControllers) // (2) if (! [vc esteMemberOfClass: [UINavigationController class]]) [tempVCs addObject: [[UINavigationController alloc] initWithRootViewController: vc];  altceva [tempVCs addObject: vc]; UIBarButtonItem * revealMenuBarButtonItem = [[UIBarButtonItem alocare] initWithTitle: @ Stilul "Meniu": UIBarButtonItemStylePlain țintă: acțiune auto: @selector (toggleMenuVisibility :); // (3) UIViewController * topVC = ((UINavigationController *) tempVCs.lastObject) .topViewController; topVC.navigationItem.leftBarButtonItems = [@ [revealMenuBarButtonItem] arrayByAddingObjectsFromArray: topVC.navigationItem.leftBarButtonItems];  self.viewControllers = [tempVCs copy]; auto.menu = [[UITableView aliniere] init]; // (4) self.menu.delegate = auto; self.menu.dataSource = auto;  întoarce-te;  - (void) viewDidLoad [vizualizare superDidLoad]; [self.menu registerClass: [Clasa UITableViewCell pentruCellReuseIdentifier: kMenuCellID]; self.menu.frame = self.view.bounds; [auto.view addSubview: auto.menu]; self.indexOfVisibleController = 0; UIViewController * visibleViewController = auto.viewControllers [0]; visibleViewController.view.frame = [auto offScreenFrame]; [self addChildViewController: visibleViewController]; // (5) [auto.view addSubview: visibleViewController.view]; // (6) self.isMenuVisible = DA; [self adjustContentFrameAccordingToMenuVisibility]; // (7) [auto.viewControllers [0] didMoveToParentViewController: auto]; // (8) - (void) toggleMenuVisibilitate: (id) expeditor // (9) self.isMenuVisible =! Self.isMenuVisible; [self adjustContentFrameAccordingToMenuVisibility];  - (void) adjustContentFrameAccordingToMenuVisibility // (10) UIViewController * visibleViewController = auto.viewControllers [auto.indexOfVisibleController]; Dimensiunea CGSize = visibleViewController.view.frame.size; dacă self.isMenuVisible [UIView animateWithDuration: 0.5 animații: ^ visibleViewController.view.frame = CGRectMake (kExposedWidth, 0, size.width, size.height); ];  altceva [UIView animateWithDuration: 0.5 animații: ^ visibleViewController.view.frame = CGRectMake (0, 0, size.width, size.height); ];  - (void) înlocuiVisibleViewControllerWithViewControllerAtIndex: (NSInteger) index // (11) if (index == self.indexOfVisibleController) retur; UIViewController * incomingViewController = auto.viewControllers [index]; incomingViewController.view.frame = [auto offScreenFrame]; UIViewController * outgoingViewController = auto.viewControllers [auto.indexOfVisibleController]; CGRect visibleFrame = auto.view.bounds; [outgoingViewController vaMoveToParentViewController: zero]; // (12) [auto addChildViewController: incomingViewController]; // (13) [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; // (14) [tranziție de sineFromViewController: outgoingViewController // (15) toViewController: durata de intrareViewController: 0.5 opțiuni: 0 animații: ^ outgoingViewController.view.frame = [self offScreenFrame];  completare: ^ (BOOL finalizat) [Animație animațieWithDuration UIV: 0.5 animații: ^ [outgoingViewController.view removeFromSuperview]; [self.view addSubview: incomingViewController.view]; incomingViewController.view.frame = visibleFrame; [[UIApplication sharedApplication] endIgnoringInteractionEvents]; // (16); [incomingViewController didMoveToParentViewController: auto]; // (17) [ieșireaViewController removeFromParentViewController]; // (18) self.isMenuVisible = NU; auto.indexOfVisibleController = index; ];  // (19): - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView retur 1;  - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) sectiunea return self.menuTitles.count;  - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: kMenuCellID]; cell.textLabel.text = auto.menuTituri [indexPath.row]; celule retur;  - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath [self replaceVisibleViewControllerWithViewControllerAtIndex: indexPath.row];  - (CGRect) offScreenFrame retur CGRectMake (auto.view.bounds.size.width, 0, self.view.bounds.size.width, self.view.bounds.size.height);  @Sfârșit

Acum pentru o explicație a codului. Părțile pe care le-am evidențiat pentru accent sunt deosebit de relevante pentru implementarea de izolare.

  1. Mai întâi, inițializatorul face o verificare simplă pentru a se asigura că fiecare controler de vizualizare a primit un titlu de meniu. Nu am făcut nicio verificare de tip pentru a ne asigura că fiecare dintre cele două matrice care au trecut la inițializator conține tipul corect de obiecte, UIViewController și NSString tipuri. S-ar putea să vă gândiți să o faceți. Rețineți că menținem tablouri pentru fiecare dintre acestea, numite viewControllers, și menuTitles.
  2. Vrem să fie un buton care, atunci când este apăsat, afișează sau ascunde meniul. Soluția mea simplă cu privire la locul unde ar trebui să fie butonul ar fi să pună fiecare controler de vizualizare primit de la inițializator în interiorul unui controler de navigație. Acest lucru ne oferă o bară de navigare liberă la care se poate adăuga un buton, cu excepția cazului în care controlerul vizualizat a fost deja un controler de navigare, caz în care nu facem nimic extra.
  3. Creăm un element de buton de bare care declanșează aspectul sau ascunderea meniului prin alunecarea controlerului vizual care este vizibil în prezent. Adăugăm-o în bara de navigare mutând orice buton existent din bara de navigare spre dreapta. Facem acest lucru deoarece controlerul de vizualizare adăugat este deja un controler de navigare cu butoane de bar pre-existente.
  4. Noi instanțiăm meniul nostru ca o vizualizare de tabel și atribuim controlerului rădăcină ca sursă de delegat și de date.
  5. În viewDidLoad, după configurarea și adăugarea vizualizării tabelului de meniuri la vizualizarea controlerului nostru, vom introduce în aplicația noastră primul controler de vizualizare din viewControllers mulțime. Prin trimiterea mesajului addChildViewController: mesajul către controlorul nostru rădăcină, facem prima noastră responsabilitate în ceea ce privește izolarea. Ar trebui să știți că acest lucru cauzează mesajul willMoveToParentViewController: să fie chemat pe controlorul copilului.
  6. Rețineți că trebuie să adăugăm în mod explicit viziunea controlerului nostru copil la ierarhia de vizualizare a părintelui!
  7. Am setat meniul să fie vizibile inițial și să apeleze o metodă care să ajusteze cadrul de vizibilitate al controlerului vizual al conținutului, luând în considerare vizibilitatea meniului. Vom examina în scurt timp detaliile acestei metode.
  8. Odată ce vizualizarea vizuală a controlorului copilului se află confortabil în ierarhia vizuală a părintelui, trimitem mesajul didMoveToParentViewController către controlerul copil suplimentar, cu de sine, instanța RootController, ca argument. În controlorul nostru pentru copii, putem implementa această metodă dacă avem nevoie.
  9. O metodă simplă conectată la acțiunea butonului barei de meniu care comută vizibilitatea meniului prin ajustarea corectă a vederii controlerului de vedere al suprapunerii.
  10. După cum indică numele, adjustContentFrameAccordingToMenuVisibility ne permite să ajustăm cadrul controlerului de vizualizare a conținutului pentru a ne spune dacă meniul este ascuns sau nu. Dacă da, atunci se suprapune supravegherea. În caz contrar, este mutat spre dreapta prin kExposedWidth. Am stabilit asta la 200 de puncte.
  11. Din nou, așa cum este clar indicat de nume, replaceVisibleViewControllerWithViewControllerAtIndex ne permite să schimbați controlorii de vizualizare și vederile corespunzătoare din ierarhie. Pentru a scoate animația, care constă în alunecarea controlerului de vizualizare înlocuit la dreapta și apoi aducerea controlerului de înlocuire din același loc, definim câteva cadre dreptunghiulare.
  12. willMoveToParentViewController cu zero. Odată ce finalizăm acest pas, acest controler de vizualizare va înceta să primească apelări de aspect și rotație de la părinte. Acest lucru are sens deoarece nu mai este o parte activă a aplicației.
  13. Adăugăm controlerul de vizualizare primit ca un copil la controlerul rădăcină, similar cu ceea ce am făcut la început.
  14. Începem ignorarea evenimentelor de interacțiune ale utilizatorilor pentru a permite schimbului de vizualizare a regulatorului nostru de vizualizare.
  15. Această metodă comodă ne permite să animăm îndepărtarea controlerului de ieșire și sosirea celui de intrare în timp ce efectuați secvența necesară a evenimentelor implicate în procesul de adăugare și de eliminare a controlerului de vedere al copilului. Animăm viziunea VC de ieșire pentru alunecare pe ecranul din dreapta și, după terminarea animației, o eliminăm din ierarhia de vizualizare. Apoi, animăm controlerul de vizualizare de intrare pentru a aluneca din același loc de pe ecran și ocupă locul anterior ocupat de vizualizarea controlerului de ieșire.
  16. Permitem aplicației noastre să accepte evenimente de interacțiune primite, deoarece schimbul de vizualizare al controlorului nostru a fost finalizat.
  17. Notificăm controlerul de vizualizare primit că a fost mutat la controlerul de containere prin trimiterea acestuia didMoveToParentViewController mesaj cu de sine ca argument.
  18. Eliminăm controlerul de ieșire de la controlerul de containere trimițându-l removeFromParentViewController mesaj. Ar trebui să știi că didMoveToParentViewController: cu zero ca un argument primit pentru tine.
  19. Implementăm metodele de delegat din tabelul de meniuri și din protocolul sursă de date, care sunt destul de simple. Aceasta include declanșarea etapei de schimbare a controlerului de vizualizare (11) atunci când o celulă a unui element nou este atinsă în meniu prin intermediul -tableView: didSelectRowAtIndexPath: metodă.

S-ar putea să fi găsit secvența de apeluri legate de controlerul de izolare un pic confuz. El ajută să rezumăm.

    Când adăugați un controler de vizualizare copil la un părinte:
  • Apel addChildViewController: pe părinte cu copilul ca argument. Acest lucru cauzează mesajul willMoveToParentViewController: să fie trimis copilului împreună cu părintele ca argument.
  • Adăugați vizualizarea copilului sub formă de subiectivă a vederii părintelui.
  • Explicit apel didMoveToParentViewController: pe copil cu părintele ca argument.
    Când eliminați un controler de vizualizare copil de la părintele său:
  • Apel willMoveToParentViewController: pe copil cu zero ca argument.
  • Îndepărtați opinia copilului din supravegherea acestuia.
  • Trimite removeFromParentViewController la copil. Cauzele mesajului didMoveToParentViewController cu zero ca argument care trebuie trimis copilului în numele dvs..

3. Testarea

Să testați diferitele tipuri de controale de vizualizare adăugate la controlerul nostru de bază! Creați o nouă subclasă de UIViewController denumit ViewController, menținând opțiunile necontrolate.

Înlocuiți codul din ViewController.m cu următorul cod.

 #import ViewController () @end @implementation ViewController - (void) willMoveToParentViewController: (UIViewController *) părinte NSLog (@ "% @ ), sine, NSStringFromSelector (_cmd));  - (void) didMoveToParentViewController: (UIViewController *) părinte NSLog (@ "% @ (% p) -% @", NSStringFromClass ([self class]), NSStringFromSelector (_cmd);  - (void) viewWillAppear: (BOOL) animat [super viewWillAppear: animat]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto clasa]), auto, NSStringFromSelector (_cmd));  - (void) vizualizareDidAppear: (BOOL) animat [super viewDidAppear: animat]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto clasa]), auto, NSStringFromSelector (_cmd));  - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) laInterfaceOrientation durată: (NSTimeInterval) durata [super willRotateToInterfaceOrientation: toInterfaceOrientation duration: duration]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto clasa]), auto, NSStringFromSelector (_cmd));  - (void) didRotateFromInterfaceOrientation: (InterfațăOrientare) dinInterfaceOrientation [super didRotateFromInterfaceOrientation: fromInterfaceOrientation]; NSLog (@ "% @ (% p) -% @", NSStringFromClass ([auto clasa]), auto, NSStringFromSelector (_cmd));  @Sfârșit

Nu există nimic special în privința controlerului nostru de vedere, cu excepția faptului că am răsturnat diferitele apeluri telefonice, astfel încât să le putem înregistra oricând ViewController instanța devine un copil pentru controlerul nostru de bază și apare un eveniment de aspect sau de rotație.

În tot codul anterior, _cmd se referă la selectorul corespunzător metodei în care executarea noastră este înăuntru. NSStringFromSelector () îl transformă într-un șir. Aceasta este o modalitate rapidă și ușoară de a obține numele metodei curente fără a fi necesar să o scrieți manual.

Să aruncăm un regulator de navigație și un controler de file în mix. De data aceasta vom folosi Storyboards.

Creați un fișier nou și sub iOS> Interfața utilizatorului, alege storyboard. Setați familia de dispozitive la iPhone, și numește-o NavStoryBoard.


De la bibliotecă de obiecte, drag and drop a Controller de navigație obiect în pânză. Trageți și fixați o element buton bar în partea stângă a barei de navigare din controlul vizualizării tabelului desemnat ca "Controler vizualizare rădăcină"Aceasta conține vizualizarea de tabelă în pânză, dați-i orice nume, am numit-o"Stânga"Scopul său este de a verifica codul pe care l-am scris pentru a face ca butonul de ascundere / dezvăluire al barei de meniu să-i înlocuiască butonul din stânga de pe bara de navigare, împingând butoanele deja prezente spre dreapta. Vizualizați controlerul și plasați-o în partea dreaptă a operatorului intitulat "Controler vizualizare rădăcină"în pânză.

Faceți clic pe unde scrie "Vizualizare tabel"în centrul celui de - al doilea controler, și în atribuie inspectorului modificați conținutul din "Prototype dinamic" la "Celule statice".

Schimbarea tipului de conținut de celule de la dinamic la static

Acest lucru va face ca trei celule statice de vizualizare a tabelului să apară în constructorul de interfață. Ștergeți numai una din aceste celule de vizualizare a tabelului și mențineți apăsat Control, faceți clic și trageți de la celula rămasă la controlerul de vizualizare de la extrema dreaptă și eliberați-o. Selectați "Apăsați" sub Selecția Segue. Toate acestea nu cauzează un pericol pentru controlerul de vizualizare dreapta atunci când apăsați pe celula singuratică din vizualizarea tabelului. Dacă doriți, puteți să renunțați la a UILabel pe celula tabelului pentru a da ceva text. Tabloul dvs. de idei ar trebui să arate similar cu fotografia de mai jos.

NavStoryBoard

În cele din urmă, să adăugăm un controler de bara de tab-uri. La fel cum ați făcut anterior, creați un storyboard fișier și apelați-l TabStoryBoard. Trageți și fixați o butonul pentru bara de butoane articol din bibliotecă de obiecte în pânză. Acesta este preconfigurat cu două file și, dacă doriți, puteți schimba culoarea de fundal a celor două controlere de vizualizare cu file, făcând clic pe vizualizarea corespunzătoare fie unui controler de vizualizare, fie schimbând butonul "fundal"în opțiunea Atribuții Inspector. În acest fel, puteți verifica dacă selectarea controlerului de vizualizare prin fila funcționează corect.

Povestea dvs. ar trebui să arate așa.

4. Configurarea delegatului aplicației

Acum este momentul să setați totul în AppDelegate.

Înlocuiți codul în AppDelegate.m cu următorul cod.

 #import "AppDelegate.h" #import "RootController.h" #import "ViewController.h" @implementation Aplicație AppDelegate - (BOOL): aplicație (UIApplication *) didFinishLaunchingWithOptions: (NSDictionary *) launchOptions self.window = [[UIWindow alin] initWithFrame: [[UIScreen mainScreen] limite]]; UIStoryboard * tabStoryBoard = [UIStoryboard storyboardWithName: @ "TabStoryboard" bundle: zero]; UIStoryboard * navStoryBoard = [UTIboardboard storyboardWithName: @ "NavStoryboard" bundle: nil]; UINavigationController * navController = [navStoryBoard instantiateViewControllerWithIdentifier: @ "Nav Controller"]; UITabBarController * tabController = [tabStoryBoard instantiateViewControllerWithIdentifier: @ "Tab Controller"]; ViewController * redVC, * greenVC; redVC = [[ViewController alocare] init]; greenVC = [[ViewController alocare] init]; redVC.view.backgroundColor = [UICcolor redColor]; greenVC.view.backgroundColor = [UICcolor verdeColor]; RootController * menuController = [[RootController alloc] initWithViewControllers: @ [tabController, redVC, greenVC, navController] șiMenuTitles: @ [@ Tab "," Red ", @ Green; self.window.rootViewController = meniuController; auto.window.backgroundColor = [UICcolor whiteColor]; [auto.window makeKeyAndVisible]; reveniți DA; 

Tot ce am făcut a fost crearea de instanțe ViewController și instanțiați controlerul de navigare și tab-ul din cele două panouri storyboard. Le-am trecut într-o gamă largă RootControllerde exemplu. Acesta este controlerul containerului pe care l-am implementat la început. Am făcut acest lucru împreună cu o serie de șiruri de caractere pentru a numi controlorii de vizualizare din meniu. Acum, pur și simplu, vom desemna instanța noastră de root-controler inițializată ca fereastra rootViewController proprietate.

Construiți și rulați aplicația. Tocmai ați pus în aplicare un container de reținere! Atingeți diferitele celule de masă din meniu pentru a înlocui diapozitivul vizibil cu cel nou care alunecă din dreapta. Observați cum, pentru instanța controlerului de navigație (numită "NavC"în meniu), meniul"Stânga"a mutat un loc în dreapta și butonul din bara de meniu a preluat poziția din stânga. Puteți schimba orientarea pe peisaj și puteți verifica dacă totul pare corect.

Simulatoare de ecran

Concluzie

În acest tutorial introductiv, am analizat modul în care este implementată controlul vizualizării controlerului în iOS 6. Am dezvoltat o versiune simplă a interfeței personalizate a aplicației, care a câștigat multă popularitate și este adesea văzută în aplicații extrem de utilizate precum Facebook și Path. Implementarea noastră a fost cât mai simplă posibil, astfel încât am reușit să o disecăm cu ușurință și să obținem corectitudinea. Există multe implementări sofisticate open-source ale acestui tip de controler pe care le puteți descărca și studia. Se va afișa o căutare rapidă pe Google JASidePAnels și SWRevealViewController, printre alții.

Iată câteva idei pentru care să lucrați.

  • Faceți implementarea mai flexibilă și API-ul mai personalizabil.
  • Faceți interfața mai frumoasă. Aveți posibilitatea să personalizați aspectul celulei de vizualizare a tabelului sau să lăsați vizualizarea controlerului dvs. să arunce o umbră în meniu pentru a împrumuta interfața cu o anumită adâncime.
  • Faceți interfața să se adapteze mai bine orientării. Amintiți-vă că controlorii de vizualizare a copiilor vor primi notificări de rotație, de aceea începeți!
  • Implementați recunoașterea gesturilor astfel încât să puteți trage un controler de vizualizare la stânga și la dreapta pe ecran ca alternativă la clic pe butonul de meniu.
  • Proiectați și dezvoltați un flux complet nou și nou de aplicații și realizați UI-ul în cod. Este posibil să aveți nevoie să utilizați dispozitivul de control al vizualizării!

Un lucru pe care aș dori să-l menționez aici este că în Xcode 4.5, există un nou obiect constructor de interfețe numit "Vizualizare container"care poate afișa conținutul unui controler de vizualizare și, astfel, să fie utilizat pentru a implementa izolarea direct în storyboard-ul dvs.!!

Cod