Containercontainment implementeren - schuifmenu-controller

In deze zelfstudie zullen we een minimalistische versie van de gebruikersinterface voor Facebook / Path-stijl implementeren. Het doel zal zijn om inzicht te krijgen in het gebruik van view controller-insluiting om aangepaste stroom in uw app te implementeren.


Theoretisch overzicht

View controllers vormen een essentieel onderdeel van elke iOS-applicatie, hoe klein, groot, eenvoudig of complex ook. Ze bieden de "lijm-logica" tussen het gegevensmodel van uw app en de gebruikersinterface.

Over het algemeen zijn er twee soorten view controllers:

  • Controllers voor inhoudweergave: Deze zijn verantwoordelijk voor het weergeven en beheren van zichtbare inhoud.
  • Containercontrollers: Deze beheren content view controllers en zij zijn verantwoordelijk voor de algemene structuur en voortgang van de app.

Een containercontroller kan een zichtbare component van zichzelf hebben, maar functioneert in principe als host voor contentview-controllers. Containercontrollers dienen voor het 'verkeer' van het komen en gaan van contentview-controllers.

UINavigationController, UITabBarController en UIPageViewController zijn voorbeelden van containerview-controllers die worden geleverd met de iOS SDK. Overweeg hoe de drie verschillen in termen van de toepassingsstromen die ze veroorzaken. De navigatiecontroller is geweldig voor een app met een dieptepunttype, waarbij de selectie die de gebruiker in één scherm maakt van invloed is op de keuzes die hij in het volgende scherm presenteert. De tabbalkcontroller is geweldig voor apps met onafhankelijke functies, waardoor u gemakkelijk kunt wisselen door eenvoudig op een tabtoets te drukken. Ten slotte presenteert de besturingseenheid voor paginaweergave een boekmetafoor, waardoor de gebruiker heen en weer kan bladeren tussen pagina's met inhoud.

Het belangrijkste om in gedachten te houden is dat een daadwerkelijke screening van inhoud die wordt gepresenteerd via een van deze containerzichtcontrollers zelf moet worden beheerd, zowel in termen van de gegevens waarvan het is afgeleid (het model) als de presentatie op het scherm (de weergave), wat opnieuw de taak van een view controller zou zijn. Nu hebben we het over content view controllers. In sommige apps, met name op de iPad, omdat op het grotere scherm meer inhoud tegelijk kan worden weergegeven, moeten mogelijk zelfs verschillende weergaven op het scherm afzonderlijk worden beheerd. Dit vereist meerdere view controllers op het scherm in een keer. Dit alles houdt in dat de view-controllers in een goed ontworpen app op een hiërarchische manier moeten worden geïmplementeerd, waarbij zowel container- als contentview-controllers hun respectieve rollen spelen.

Vóór iOS 5 waren er geen manieren om een ​​hiërarchische (dat wil zeggen, ouder-kind) relatie tussen twee view-controllers te declareren en daarom geen 'juiste' manier om een ​​aangepaste applicatiestroom te implementeren. Een van de twee moest het doen met de ingebouwde typen, of op een lukrake manier, die in feite bestond uit het vasthouden van weergaven die werden beheerd door een view-controller in de weergavehiërarchie van de weergave die werd beheerd door een andere view-controller. Dit zou inconsistenties creëren. Een weergave zou bijvoorbeeld in de weergavehiërarchie van twee controllers terechtkomen zonder dat een van deze controllers de andere herkent, wat soms tot vreemd gedrag leidt. Containment werd geïntroduceerd in iOS 5 en enigszins verfijnd in iOS 6, en het biedt de mogelijkheid om ouder- en kindzichtcontrollers in een hiërarchie te formuleren. In feite vereist een correcte weergavebesturingselementconfiguratie dat als weergave B een subweergave (kind) van weergave A is en als deze niet onder het beheer van dezelfde weergavecontroller staan, B's weergavecontroller dan moet worden gemaakt als A's view controller's child.

U kunt zich afvragen of er sprake is van een concreet voordeel geboden door view controller containment naast het voordeel van het hiërarchische ontwerp dat we hebben besproken. Het antwoord is ja. Houd er rekening mee dat wanneer een weergaveregelaar op het scherm wordt weergegeven of verdwijnt, we mogelijk bronnen moeten instellen of verwijderen, informatie opruimen, ophalen of opslaan van / naar het bestandssysteem. We kennen allemaal uiterlijk callbacks. Door de ouder-kindrelatie expliciet te verklaren, zorgen we ervoor dat de bovenliggende controller callbacks doorstuurt naar zijn kinderen wanneer iemand op het scherm verschijnt of van het scherm gaat. Rotatie-callbacks moeten ook worden doorgestuurd. Wanneer de oriëntatie verandert, moeten alle view controllers op het scherm dit weten zodat ze hun inhoud op de juiste manier kunnen aanpassen.

Wat houdt dit allemaal in, in termen van code? View-controllers hebben een NSArray eigenschap genoemd childViewControllers en onze verantwoordelijkheden omvatten het toevoegen en verwijderen van child view controllers van en naar deze array in de ouder door geschikte methoden aan te roepen. Deze methoden omvatten addChildViewController (een beroep gedaan op de ouder) en removeFromParentViewController (riep het kind op) wanneer we de ouder-kindrelatie willen maken of breken. Er zijn ook een paar notificatieberichten verzonden naar de child view-controller aan het begin en aan het einde van het toevoegings- / verwijderingsproces. Dit zijn willMoveToParentViewController: en didMoveToParentViewController:, verzonden met de juiste bovenliggende controller als argument. Het argument is nul, als het kind wordt verwijderd. Zoals we zullen zien, zal een van deze berichten automatisch voor ons worden verzonden, terwijl de andere onze verantwoordelijkheid is om te verzenden. Dit hangt ervan af of we het kind toevoegen of verwijderen. We zullen de exacte volgorde kort bestuderen wanneer we dingen in code implementeren. De child-controller kan op deze meldingen reageren door de bijbehorende methoden te implementeren als deze iets moet doen ter voorbereiding van deze evenementen.

We moeten ook de aan de child view-controller gekoppelde views toevoegen / verwijderen aan de hiërarchie van de parent, met behulp van methoden zoals addSubview: of removeFromSuperview), inclusief het uitvoeren van eventuele begeleidende animaties. Er is een gemaksmethode (-) transitionFromViewController: toViewController: duur: options: animaties: voltooiing: waarmee we het proces van het wisselen van besturingselementen voor kinderopvragingen op het scherm met animaties kunnen stroomlijnen. We zullen de exacte details bekijken wanneer we de code schrijven - wat de volgende is!


1. Een nieuw project maken

Maak een nieuwe iOS-app in Xcode op basis van de "Lege applicatie"template. Maak er een iOS-app van met ARC ingeschakeld VCContainmentTut.

Een nieuw project maken

2. Implementatie van de Container View Controller

Maak een nieuwe klasse genaamd RootController. Maak het een UIViewController subklasse. Zorg ervoor dat selectievakjes niet zijn geselecteerd. Dit wordt onze subklasse voor containerzichtcontrollers.


Vervang de code in RootViewController.h met het volgende.

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

Onze containercontroller heeft een tabelweergave die functioneert als ons menu. Als u op een cel tikt, wordt de momenteel zichtbare view-controller vervangen door degene die is geselecteerd via de tik van de gebruiker..

Verwijzend naar de punten in de code,

  1. Onze rootcontroller fungeert ook als delegeer- en gegevensbron van het menu (d.w.z. de tabelweergave).
  2. We bieden een uiterst eenvoudige API (voor zover het onze gebruikers van de containerklasse betreft), bestaande uit één initialisatie-eenheid die een lijst met view-controllers neemt die onze root-controller zal bevatten, en een lijst van strings die de titels voor elke view controller in de menu. Dit is zodat we ons kunnen concentreren op de basis. Zodra u deze begrijpt, kunt u de API zo aanpassen als u wilt.

Laten we een kijkje nemen om te zien hoe ons eindproduct eruit zal zien, zodat u een mentaal beeld hebt om de implementatie aan te koppelen.


Het helpt ons te beseffen dat onze containerzichtcontroller vrij veel lijkt op een tabbladweergavecontroller. Elk item in het menu komt overeen met een onafhankelijke view controller. Het verschil tussen onze "glijdend menu"controller en de tab-controller zijn grotendeels visueel."glijdend menu"is een beetje een verkeerde benaming omdat het eigenlijk de contentview-controller is die verschuift om het onderliggende menu te verbergen of te onthullen.

Ga verder met de implementatie en vervang alle code in RootController.m met de volgende code.

 #define kExposedWidth 200.0 #define kMenuCellID @ "MenuCell" #import "RootController.h" @interface RootController () @eigenschap (niet-atomisch, sterk) UITableView * -menu; @property (nonatomic, strong) NSArray * viewControllers; @property (nonatomic, strong) NSArray * menuTitels; @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, @ "Er moet één en slechts één menutitel zijn die overeenkomt met elke view-controller!"); // (1) NSMutableArray * tempVCs = [NSMutableArray arrayWithCapacity: viewControllers.count]; self.menuTitles = [menuTitels kopiëren]; for (UIViewController * vc in viewControllers) // (2) if (! [vc isMemberOfClass: [UINavigationController class]]) [tempVCs addObject: [[UINavigationController alloc] initWithRootViewController: vc]];  else [tempVCs addObject: vc]; UIBarButtonItem * revealMenuBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: @ "Menu" -stijl: UIBarButtonItemStylePlain-doel: zelfactie: @selector (toggleMenuVisibility :)]; // (3) UIViewController * topVC = ((UINavigationController *) tempVCs.lastObject) .topViewController; topVC.navigationItem.leftBarButtonItems = [@ [revealMenuBarButtonItem] arrayByAddingObjectsFromArray: topVC.navigationItem.leftBarButtonItems];  self.viewControllers = [tempVCs kopiëren]; self.menu = [[UITableView alloc] init]; // (4) self.menu.delegate = self; self.menu.dataSource = self;  terugkeer zelf;  - (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 addChildViewController: visibleViewController]; // (5) [self.view addSubview: visibleViewController.view]; // (6) self.isMenuVisible = YES; [self adjustContentFrameAccordingToMenuVisibility]; // (7) [self.viewControllers [0] didMoveToParentViewController: self]; // (8) - (void) toggleMenuVisibility: (id) afzender // (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 animations: ^ visibleViewController.view.frame = CGRectMake (kExposedWidth, 0, size.width, size.height); ];  else [UIView animateWithDuration: 0.5 animations: ^ visibleViewController.view.frame = CGRectMake (0, 0, size.width, size.height); ];  - (void) replaceVisibleViewControllerWithViewControllerAtIndex: (NSInteger) index // (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 addChildViewController: incomingViewController]; // (13) [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; // (14) [self transitionFromViewController: outgoingViewController // (15) toViewController: incomingViewController duration: 0.5 options: 0 animations: ^ outgoingViewController.view.frame = [self offScreenFrame];  completion: ^ (BOOL finished) [UIView animateWithDuration: 0.5 animations: ^ [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) sectie return self.menuTitles.count;  - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: kMenuCellID]; cell.textLabel.text = self.menuTitles [indexPath.row]; terugkeer cel;  - (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);  @end

Nu voor een uitleg van de code. De onderdelen die ik heb benadrukt vanwege de nadruk, zijn met name relevant voor de insluiting-implementatie.

  1. Ten eerste voert de initialisator een eenvoudige controle uit om er zeker van te zijn dat elke weergavecontroller een menutitel heeft gekregen. We hebben geen typecontrole uitgevoerd om ervoor te zorgen dat elk van de twee matrices die aan de initializer zijn doorgegeven, de juiste soort objecten bevat, UIViewController en NSString typen respectievelijk. Je zou kunnen overwegen om het te doen. Merk op dat we reeksen onderhouden voor elk van deze, genaamd viewcontrollers, en menuTitles.
  2. We willen dat er een knop is die, wanneer erop wordt getikt, het menu toont of verbergt. Mijn eenvoudige oplossing met betrekking tot waar de knop zou moeten zijn, was om elke view-controller die we van de initializer kregen in een navigatiecontroller te plaatsen. Dit geeft ons een gratis navigatiebalk waaraan een knop kan worden toegevoegd, tenzij de verstreken in-beeldcontroller al een navigatiecontroller was, in welk geval we niets extra's doen.
  3. We maken een item in de barknop waarmee het uiterlijk van het menu wordt weergegeven of verborgen door de zichtbare viewer te verschuiven. We voegen het toe aan de navigatiebalk door bestaande knoppen op de navigatiebalk naar rechts te verplaatsen. We doen dit omdat de toegevoegde view-controller al een navigatie-controller is met reeds bestaande balknoppen.
  4. We instantiëren ons menu als een tabelweergave en kennen de rootcontroller zelf toe als de gemachtigde en de gegevensbron.
  5. In viewDidLoad, na het configureren en toevoegen van de menutabelweergave aan de weergave van onze root-controller, brengen we in onze app de eerste view-controller in de viewcontrollers rangschikking. Door de addChildViewController: bericht aan onze root-controller voeren we onze eerste inperkingsgerelateerde verantwoordelijkheid uit. U moet weten dat dit de melding veroorzaakt willMoveToParentViewController: worden opgeroepen op de kindcontroller.
  6. Houd er rekening mee dat we de weergave van onze child-controller expliciet moeten toevoegen aan de weergavehiërarchie van de ouder!
  7. We hebben het menu ingesteld om in eerste instantie zichtbaar te zijn en een methode aan te roepen die het frame van de zichtbare inhoudweergavecontroller aanpast, rekening houdend met de zichtbaarheid van het menu. We zullen de details van deze methode binnenkort bekijken.
  8. Zodra de weergave van de child view-controller comfortabel in de weergavehiërarchie van de ouder zit, we sturen het didMoveToParentViewController-bericht naar de toegevoegde child controller, met zelf, de RootController-instantie, als het argument. In onze kindcontroller kunnen we deze methode implementeren als dat nodig is.
  9. Een eenvoudige methode die is gekoppeld aan de actie van onze menubalkknop die de zichtbaarheid van het menu wijzigt door de weergave van de overlappende view controller op de juiste manier aan te passen.
  10. Zoals de naam aangeeft, adjustContentFrameAccordingToMenuVisibility laat ons het frame van de contentview-controller aanpassen om ons te laten weten of het menu verborgen is of niet. Zo ja, dan overlapt het de superview. Anders wordt deze doorgeschoven naar rechts kExposedWidth. Ik heb dat ingesteld op 200 punten.
  11. Nogmaals, zoals duidelijk aangegeven door de naam, replaceVisibleViewControllerWithViewControllerAtIndex stelt ons in staat om view controllers en de corresponderende views uit de hiërarchie uit te wisselen. Om onze animatie, die bestaat uit het opzij schuiven van de vervangen beeldcontroller naar rechts en het vervolgens van de plaats halen van de vervangende controller, af te beelden, definiëren we enkele rechthoekige frames..
  12. willMoveToParentViewController met nul. Zodra we deze stap hebben voltooid, stopt deze weergave-controller met het ophalen van weergave- en rotatie-callbacks van de ouder. Dit is logisch omdat het niet langer een actief onderdeel van de app is.
  13. We voegen de inkomende view-controller toe als een kind aan de root-controller, vergelijkbaar met wat we in het begin hebben gedaan.
  14. We beginnen met het negeren van gebruikersinteractie-evenementen om onze view controller soepel te laten wisselen.
  15. Met deze gemaksmethode kunnen we de verwijdering van de uitgaande controller animeren en de aankomst van de binnenkomende controller tijdens het uitvoeren van de vereiste reeks gebeurtenissen die zijn betrokken bij het toevoegen en verwijderen van de child view-controller. We animeren de weergave van de uitgaande VC om van het scherm naar rechts te schuiven en nadat de animatie is voltooid, verwijderen we deze uit de weergavehiërarchie. Vervolgens animeren we de binnenkomende view-controller om van dezelfde plaats naar buiten te schuiven en de plaats in te nemen die eerder was ingenomen door de weergave van de vertrekkende controller.
  16. We stellen onze app in staat om inkomende interactie-evenementen te accepteren, omdat onze view controller-swap is voltooid.
  17. We stellen de binnenkomende view-controller op de hoogte dat deze naar de container-controller is verplaatst door deze te verzenden didMoveToParentViewController bericht met zelf als het argument.
  18. We verwijderen de uitgaande controller uit de containercontroller door deze te verzenden removeFromParentViewController bericht. Je zou dat moeten weten didMoveToParentViewController: met nul als een argument voor je wordt verzonden.
  19. We implementeren de methoden voor gedelegeerde en gegevensbronprotocolmen van de menutabelweergave, die vrij eenvoudig zijn. Dit omvat het activeren van de stap van het wisselen van view-controller (11) wanneer de cel van een nieuw item in het menu wordt aangeraakt via de -tableView: didSelectRowAtIndexPath: methode.

Mogelijk hebt u de reeks oproepen met betrekking tot de beheersing van de controller een beetje verwarrend gevonden. Het helpt om samen te vatten.

    Bij het toevoegen van een child view-controller aan een ouder:
  • telefoontje addChildViewController: op de ouder met het kind als argument. Dit veroorzaakt het bericht willMoveToParentViewController: naar het kind gestuurd worden met de ouder als argument.
  • Voeg de weergave van het kind toe als een subweergave van de weergave van de ouder.
  • Bel expliciet didMoveToParentViewController: op het kind met de ouder als argument.
    Bij het verwijderen van een child view-controller van de bovenliggende:
  • telefoontje willMoveToParentViewController: op het kind met nul als het argument.
  • Verwijder het zicht van het kind uit zijn superview.
  • Sturen removeFromParentViewController voor het kind. De oorzaak van het bericht didMoveToParentViewController met nul als het argument dat namens u aan het kind moet worden gestuurd.

3. Testen

Laten we de verschillende typen view controllers testen die aan onze root-controller zijn toegevoegd! Maak een nieuwe subklasse van UIViewController riep ViewController, alle opties uitgeschakeld houden.

Vervang de code in ViewController.m met de volgende code.

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

Er is niets speciaals aan onze view controller zelf, behalve dat we de verschillende callbacks hebben overschreven, zodat we ze kunnen loggen wanneer onze ViewController instance wordt een kind voor onze root-controller en er treedt een verschijning of rotatie op.

In alle voorgaande code, _cmd verwijst naar de selector die overeenkomt met de methode waarin onze uitvoering zich bevindt. NSStringFromSelector () converteert het naar een string. Dit is een snelle en gemakkelijke manier om de naam van de huidige methode te krijgen zonder deze handmatig te hoeven typen.

Laten we een navigatiecontroller en een tabcontroller in de mix gooien. Deze keer gebruiken we Storyboards.

Maak een nieuw bestand, en onder iOS> Gebruikersinterface, Kiezen storyboard. Stel de apparaatfamilie in iPhone, en noem het NavStoryBoard.


Van de objecten bibliotheek, slepen en neerzetten a Navigatiecontroller object in het canvas. Versleep a streepjesknopitem links in de navigatiebalk in de tafelweergave controller aangeduid als "Root View Controller". Dit bevat de tabelweergave op het canvas. Geef het een naam. Ik heb het genoemd"Links"Het doel is om de code die we hebben geschreven te verifiëren om de knop verbergen / zichtbaar maken van de menubalk als de meest linkse knop op de navigatiebalk te vervangen door de reeds aanwezige knoppen naar rechts te duwen. Bekijk Controller voorbeeld en plaats deze rechts van de controller met de titel 'Root View Controller"op het canvas.

Klik waar het staat "Tabelweergave"in het midden van de tweede controller en in de attributen inspector verander de inhoud van "Dynamisch prototype" naar "Statische cellen".

Het celinhoudstype wijzigen van dynamisch in statisch

Hierdoor verschijnen er drie statische cellen in de tabelweergave in de interfacebuilder. Verwijder alle cellen op één na, maar houd ze ingedrukt Controle, klik en sleep van de overgebleven cel naar de view-controller uiterst rechts en laat los. Selecteer "Duwen" onder Selectie Segue. Dit alles zorgt ervoor dat er een segue naar de rechterview-controller gaat als u in de tabelweergave op de eenzame cel tikt. Als je wilt, kun je een a laten vallen UILabel op de tafelcel om het wat tekst te geven. Je storyboard moet er ongeveer zo uitzien als de onderstaande foto.

NavStoryBoard

Laten we tot slot een tabbalkcontroller toevoegen. Net zoals je eerder hebt gedaan, maak een storyboard bestand en bel het TabStoryBoard. Versleep a tabbalkcontroller item uit de objectbibliotheek in het canvas. Het wordt voorgeconfigureerd met twee tabbladen en als je wilt, kun je de achtergrondkleur van de twee weergaveregelaars met tabbladen wijzigen door te klikken op de weergave die overeenkomt met de view controller en de "achtergrond"optie in de Kenmerken Inspector. Op deze manier kunt u controleren of de selectie van de weergaveregelaar via het tabblad correct werkt.

Je storyboard zou er zo uit moeten zien.

4. De app-gedelegeerde configureren

Nu is het tijd om alles in te stellen in de AppDelegate.

Vervang de code in AppDelegate.m door de volgende code.

 #import "AppDelegate.h" #import "RootController.h" #import "ViewController.h" @implementation AppDelegate - (BOOL) -toepassing: (UIApplication *) -toepassing didFinishLaunchingWithOptions: (NSDictionary *) launchOptions self.window = [[UIWindow toewijzen] initWithFrame: [[UIScreen mainScreen] bounds]]; UIStoryboard * tabStoryBoard = [UIStoryboard storyboardWithName: @ "TabStoryboard" -bundel: nihil]; UIStoryboard * navStoryBoard = [UIStoryboard storyboardWithName: @ "NavStoryboard" -bundel: nihil]; 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] enMenuTitles: @ [@ "Tab", @ "Red", @ "Green", @ "Nav"]]; self.window.rootViewController = menuController; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; terugkeer JA; 

Alles wat we deden was het creëren van instanties van ViewController en maak een begin met de navigatie- en tabcontroller van de twee storyboards. We hebben ze in een array doorgegeven aan ons RootController's exemplaar. Dat is de containercontroller die we bij de start hebben geïmplementeerd. We deden dit samen met een array van strings om de view controllers in het menu te noemen. Nu zullen we onze geïnitialiseerde Root Controller-instantie gewoon als venster aanduiden rootViewController eigendom.

Bouw en voer de app uit. U hebt zojuist Container containment geïmplementeerd! Tik op de verschillende tabelcellen in het menu om de zichtbare dia te vervangen door de nieuwe dia van rechts. Merk op hoe, voor de navigatiecontroller-instantie (genaamd "NavC"in het menu), de"Linksknop is een plaats naar rechts verschoven en de menubalkknop heeft de meest linkse positie ingenomen. U kunt de richting wijzigen in liggend en controleren of alles er goed uitziet.

Simulator schermafbeeldingen

Conclusie

In deze inleidende zelfstudie hebben we gekeken naar hoe view controller-insluiting is geïmplementeerd in iOS 6. We hebben een eenvoudige versie van een aangepaste app-interface ontwikkeld die veel populariteit heeft gekregen en vaak wordt gezien in veelgebruikte apps zoals Facebook en Path. Onze implementatie was zo eenvoudig mogelijk, dus we konden het gemakkelijk ontleden en de basis goed krijgen. Er zijn veel geavanceerde open-sourceimplementaties van dit type controller die u kunt downloaden en bestuderen. Er verschijnt een snelle Google-zoekopdracht JASidePAnels en SWRevealViewController, onder andere.

Hier zijn enkele ideeën om aan te werken.

  • Maak de implementatie flexibeler en de API beter aanpasbaar.
  • Maak de interface mooier. U kunt de celweergave van de tabelweergave aanpassen of de weergave van uw view controller een schaduw op het menu geven om de interface enige diepte te geven.
  • Zorg dat de interface zich beter aanpast aan de richting. Vergeet niet dat uw child view-controllers rotatiemeldingen zullen ontvangen, dus dat is waar u begint!
  • Implementeer gebaarherkenning zodat u een weergavecontroller naar links en rechts over het scherm kunt slepen, als een alternatief voor het klikken op de menuknop.
  • Ontwerp en ontwikkel een volledig nieuwe en nieuwe app-stroom en realiseer de UI in code. De kans is groot dat je gebruik moet maken van view controller containment!

Een ding dat ik hier wil vermelden is dat er vanaf Xcode 4.5 een nieuw interface builder-object is genaamd "Containerweergave"die de inhoud van een view-controller kan weergeven en dus kan worden gebruikt om containment direct in je storyboard te implementeren! Happy coding!