2013-08-04 3 views
5

Ho un controller di visualizzazione contenitore personalizzato: ContainerVC. Il suo compito è presentare uno dei due controller di visualizzazione del contenuto: ContentPortraitVC o ContentLandscapeVC, a seconda dell'orientamento corrente (anche se non importa perché il contenitore sceglie la sua vista, presumo). ContentPortraitVC, a un certo punto appare ContentModalDetailVC.Come interagiscono i controller Modal e Child View?

Quindi ci sono due diversi metodi di visualizzazione di nuovi contenuti al lavoro qui:

  • la relazione padre-e-figlio (istigato via addChildViewController e rimosso tramite removeFromParentViewController),

  • il presenting- e-relazione presentata (istigata tramite presentViewController e rimossa tramite dismissViewController).

Se il ContainerVC aggiunge la ContentPortraitVC, che poi presenta la ContentModalDetailVC, e poi il ContainerVC decide di passare alla ContentLandscapeVC, il ContentModalDetailVC resta visibile (perché non viene rimosso quando suo padre viene rimosso?)

Tuttavia, quando viene chiesto di rimuovere ContentPortraitVC per rimuovere ContentModalDetailVC, non accade nulla. Il display modale rimane inserito. Cosa sta succedendo?

risposta

4
  1. Quando si utilizza addChildViewController aggiungere la ContentPortraitVC:

    a. Il ContentPortraitVC ottiene il suo insieme di proprietà parentViewController.

    b. Quindi, come per la documentazione Apple, è necessario visualizzare manualmente la vista di ContentPortraitVC. Se si segue la documentazione, lo si fa aggiungendolo come figlio della vista di livello superiore di ControllerVC.

  2. Il ContentPortraitVC poi chiama presentViewController per visualizzare ContentModalDetailVC.

    a. Questo imposta la sua proprietà presentingViewController (nel debugger questo è mostrato come il _parentModalViewController ivar - nota che ivar è diverso dalla proprietà) e imposta la proprietà presentedModalViewController dello ContentPortraitVC (chi è ivar è _childModalViewcontroller).

    b. Visto da vicino, su iPhone, la vista di ContentModalDetailVC sostituirà completamente le visualizzazioni da ContentPortraitVC e ContainerVC, quindi sarà visibile solo la vista del controller di visualizzazione modale. (su iPad, mette a strati la nuova interfaccia utente sopra la parte superiore, ma come una coppia della vista ControllerVC, che a sua volta è la schermata principale di ContentPortraitVC).

  3. Così ora, la transizione da ContentPortraitVC a ContentLandscapeVC.

    a. IOS fa un po 'di magia. Sa che la cosa che stai rimuovendo (ContentPortraitVC) ha un presentedViewController attualmente attivo, quindi cambia il suo genitore.Imposta il valore su nil su ContentPortraitVC, prende il bambino (ContentModalDetailVC) e imposta il padre sulla nuova visualizzazione (ContentLandscapeVC). Quindi ora il controller di visualizzazione che ha presentato la vista modale non è più il suo controller di visualizzazione di presentazione. È come se ContentLandscapeVC lo presentasse in primo luogo!

    b. In termini di visualizzazioni, si segue la documentazione Apple per modificare la vista da ContentPortraitVC a ContentLandscapeVC. Ma stai semplicemente cambiando le sottoview della vista di ControllerVC. Su iPhone, il controller di visualizzazione modale è ancora l'unica cosa visualizzata, quindi fare la modifica non fa nulla sullo schermo. Su iPad, lo fa (anche se probabilmente non lo vedrai, visto che la vista modale di solito è a schermo intero).

  4. Ora viene a chiudere la vista modale. Presumibilmente lo fai in ContentPortraitVC, ma non ha più alcun riferimento alla cosa che ha presentato. Quindi chiamare [self dismissViewController... non fa nulla, perché ContentPortraitVC non presenta più nulla, la responsabilità è passata allo ContentLandscapeVC.

Ecco cosa succede e perché. Ecco cosa fare al riguardo.

  1. È possibile ricollegare manualmente il delegato quando si cambia ContentPortraitVC-ContentLandscapeVC, in modo che il secondo è quello che cerca di respingere il controller modale.

  2. È possibile disattivare il controller modale con [self dismissModalControllerAnimated:YES completion:nil]. Ho intenzione di chiedere e rispondere ad un'altra domanda sul perché funziona (come fa l'IOS a sapere quale licenziare?), Se ciò sembra strano.

  3. È possibile avere lo ControllerVC quello che apre la vista modale ed è responsabile della sua rimozione.

+0

Mi sono imbattuto in questo problema e ho capito cosa sta succedendo da questa risposta, grazie! Per quanto riguarda la gestione del caso dei controller di visualizzazione presentati nel controller di visualizzazione contenitore quando si passa? Cioè controllando la presenza di un 'presentViewController' sul controller corrente della vista figlio e sostituendo quella vista. Questo spezzerebbe il design? – kolizz

0

Se si controlla il presentingViewControllerContentModalDetailVC, vedrete che in realtà è presentato da ContainerVC e non ContentPortraitVC.

Per risolvere questo problema, è sufficiente impostare definesPresentationContext (o utilizzare la casella di controllo "Definisci contesto" in Interface Builder) su ContentPortraitVC.

Questo dirà a ContentPortraitVC di gestire la presentazione modale invece di passare la catena di risposta al controller di visualizzazione successivo che definisce il contesto di presentazione (il controller di visualizzazione di root per impostazione predefinita).

Probabilmente vorrai che lo ContentLandscapeVC definisca il contesto per evitare lo stesso problema.

Con entrambi i controller figlio che definiscono il proprio contesto di presentazione, quando ContainerVC decide di scambiare i bambini, qualsiasi modale modale verrà rimosso dalla nuova gerarchia insieme al bambino che lo ha presentato. Non c'è bisogno di fare cose hacky per provare a liquidare prima di scambiare :)