Come funziona il contenimento del controller di visualizzazione in iOS 5?


108

In WWDC 2011 Sessione 102, Apple ha introdotto View Controller di contenimento, che è la capacità di creare contenitori controller della vista su misura, analoga a UITabBarController, UINavigationControllere simili.

Ho guardato gli esempi più volte. Ci sono una raffica di metodi associati a questo modello, ma è stato un po 'difficile capirli esattamente. Pubblicherò qui quello che penso stia succedendo e vedrò se la comunità confermerà o smentirà i miei sospetti.

Scenario 1: passaggio da nessun genitore a un nuovo controller di visualizzazione padre

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Le prime due righe devono comparire nell'ordine dato o possono essere invertite?

Scenario 2: passaggio da un controller di visualizzazione padre a nessun controller di visualizzazione padre

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

È anche necessario chiamare [vc didMoveToParentViewController:nil]? Gli esempi nella Sessione 102 non hanno funzionato in questo scenario, ma non so se fosse un'omissione o meno.

Scenario 3: passaggio da un controller di visualizzazione padre a un altro

Ciò si verificherà probabilmente nel modo seguente, poiché la logica in ogni controller di visualizzazione padre verrà incapsulata.

// In the old parent
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

// In the new parent
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];

Domande

La mia domanda principale è questa: è così che dovrebbe funzionare il contenimento del controller di visualizzazione, in generale? I meccanismi sopra indicati sono corretti?

È necessario chiamare willMoveToParentViewControllerprima di chiamare addChildViewController? Questo mi sembra l'ordine logico, ma è strettamente necessario?

È necessario chiamare didMoveToParentViewController:nildopo aver chiamato removeFromParentViewController?

Risposte:


72

I UIViewControllerdocumenti sono abbastanza chiari su quando e quando non chiamare willMove/ didMovemetodi. Consulta la documentazione "Implementing a Container View Controller" .

I documenti dicono che se non esegui l'override addChildViewController, non devi chiamare il willMoveToParentViewController:metodo. Tuttavia, è necessario chiamare il didMoveToParentViewController:metodo dopo che la transizione è stata completata. "Allo stesso modo, è responsabilità del controller di visualizzazione del contenitore chiamare il willMoveToParentViewController:metodo prima di chiamare il removeFromParentViewControllermetodo. Il removeFromParentViewControllermetodo chiama il didMoveToParentViewController:metodo del controller di visualizzazione figlio."

Inoltre, c'è un esempio elaborato qui e un codice di esempio qui .

In bocca al lupo


17
Capisco, quindi addChildViewControllerdovrebbe essere bilanciato con didMoveToParentViewControllere willMoveToParentViewControllerdovrebbe essere bilanciato con removeFromParentViewController. Questo e 'esattamente quello che stavo cercando. Non sono sicuro di come mi sia perso nei documenti.
Gregory Higley

Perchè no? Perché non devi chiamare willMoveToParentViewController ma devi chiamare didMoveToParentViewController?
user4951

Perché è quello che dicono i dottori. Apple ovviamente sente che non abbiamo bisogno di saperlo.

7
Il motivo è per il bene dell'animazione: supponiamo che tu stia creando il tuo controller di navigazione. All'inizio di un'animazione slide-in, deve essere chiamato "willMove" e alla fine dell'animazione, deve essere chiamato "didMove". Ora, quando chiami 'addChild' all'inizio dell'animazione, automaticamente chiama 'willMove' per te. Ma non può sapere quando l'animazione (se ce n'è una) finisce, quindi devi chiamare 'didMove' manualmente alla fine dell'animazione (o immediatamente in assenza di animazione).
Chris

2
E come per un'animazione "slide out", ad esempio il bambino viene rimosso, devi chiamare "willMove" manualmente all'inizio dell'animazione, perché uikit altrimenti non saprebbe quando chiamare "viewWillDisappear" di tuo figlio VC. E alla fine dell'animazione, quando chiami removeFromParentViewController, può chiamare automaticamente "didMove".
Chris

23

Questa parte non è corretta:

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Secondo i documenti:

Quando il tuo contenitore personalizzato chiama il metodo addChildViewController:, chiama automaticamente il metodo willMoveToParentViewController: del controller di visualizzazione da aggiungere come figlio prima di aggiungerlo.

Quindi non hai bisogno della [vc willMoveToParentViewController:self]chiamata. Viene eseguito automaticamente quando chiami [self addChildViewController:vc]. Ecco di nuovo il codice di esempio:

[self addChildViewController:vc];
// [vc willMoveToParentViewController:self] called automatically
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Per rimuovere i controller di visualizzazione:

Il metodo removeFromParentViewController chiama automaticamente il metodo didMoveToParentViewController: del controller di visualizzazione figlio dopo aver rimosso l'elemento figlio.

Presumibilmente questa chiamata lo è [oldVC didMoveToParentViewController:nil].

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically

sembra che se fatto diversamente, anche se sembra funzionare, il presentViewController non è impostato sul presentViewController.
Adrian

I documenti dicono di chiamare didMoveToParentViewController " immediatamente dopo aver chiamato addChildViewController: method", non specifica quando si aggiunge effettivamente la sottoview secondaria. Mi chiedo se tutti si siano sbagliati. C'è un esempio in alcuni documenti Apple con cui possiamo verificarlo?
Robert

Nota: si fa bisogno di chiamare willMoveToParentViewControllerprima addChildViewControllerse la voce che si sta spostando è una classe personalizzata con sovrascritto addChildViewController(a meno che la sostituzione chiama internamente)
bunkerdive
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.