Avviso: -Presentanti controller di visualizzazione su controller di visualizzazione separati sono sconsigliati


180

Nella mia app, sto usando un controller di navigazione. Più avanti in qualche vista sto usando presentViewControllerper mostrare un'immagine ingrandita. Inoltre non sto usando uno storyboard o un pennino.

Ricevo questo errore solo in iOS 7. Funziona bene su iOS 6 e precedenti:

La presentazione di controller di visualizzazione su controller di visualizzazione separati è sconsigliata


Non l'ho ancora capito. Ma nella mia app non sto assegnando alcun viewcontroller a window.rootviewcontroller. sto aggiungendo vista alla finestra. Forse è questo il motivo per me. ma non sono sicuro ...
Gagan Joshi

@GaganJoshi Il motivo sopra menzionato potrebbe non essere la causa. Anche io sto affrontando lo stesso problema. E nel nostro progetto sto assegnando un controller di visualizzazione a window.rootviewcontroller.
Rajesh,

1
Penso che gli altri commenti lo mettano correttamente in relazione con qualcosa su rootViewController e la connessione alla finestra. Non l'ho ancora capito, ma sono stato in grado di aggirare il problema presentando il controller direttamente sul rootViewController invece che sul controller di navigazione o su uno dei suoi figli.
Rich Waters,

Risposte:


207

Per evitare di ricevere l'avviso in una navigazione push, è possibile utilizzare direttamente:

[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];

E poi nel tuo controller di visualizzazione modale, quando tutto è finito, puoi semplicemente chiamare:

[self dismissViewControllerAnimated:YES completion:nil];


Sto presentando il selettore di immagini con questo codice di riga "[self.view.window.rootViewController presentViewController: viewController animato: SÌ completamento: zero];" Ma non è possibile eliminare la visualizzazione di pollame con questa riga "[self dismissViewControllerAnimated: YES completamento: zero];" Qualsiasi opzione alternativa per dismisscontroller
kb920

@keyurbhalodiya È necessario chiamare il metodo dismissViewController da modalView per farlo funzionare. Pertanto, se hai visualizzato una vista denominata viewB da una viewA con [viewA.window.rootViewController presentViewController: viewB], in viewB, ad esempio, devi aggiungere un pulsante, associato ad un'azione personalizzata chiamata [self dismissViewControllerAnimated]. È più chiaro?
cdescours,

11
Non presenta viewcontroller in iOS 8.
Rajesh Maurya,

1
per iOS 8: [self.view.window.rootViewController.navigationController
Fede Cugliandolo

31
usando self.navigationControllerlo ha fatto per me.
Brandon Zacharie il

62

Il motivo di questo avviso è che stavo presentando un controller di visualizzazione su una visualizzazione piccola che non è una visualizzazione a dimensione intera. Di seguito è riportata l'immagine del mio progetto. dove su fare clic su quattro opzioni sopra. L'utente passa alla vista di childviewcontroller diversa (funziona come tabViewcontroller). Ma il childviewcontroller contiene una vista di piccole dimensioni. Quindi, se presentiamo una vista da childviewcontroller, viene visualizzato questo avviso.

vista dettaglio principale

E per evitarlo, puoi presentare una vista sul genitore di childviewcontroller

  [self.parentViewController presentViewController:viewController animated:YES completion:nil];

1
[self.view.window.rootViewController.navigationController pushViewController: YOUR_VIEW_CONTROLER animato: SÌ];
Fede Cugliandolo,

1
"presentava un controller di visualizzazione su una visualizzazione piccola che non è una visualizzazione a schermo intero". ... ESATTAMENTE. Bel lavoro.
Fattie,

61

Attendere viewDidAppear():

Questo errore può verificarsi anche se si sta tentando di presentare il controller di visualizzazione prima che la visualizzazione venga effettivamente visualizzata, ad esempio presentando la vista in viewWillAppear()o precedente. Prova a presentare un'altra vista dopo viewDidAppear()o al suo interno.


9
In altre parole, non presentare alcun controller di visualizzazione viewDidLoad(), gente! Ho fatto questo errore così tante volte ...
T Blank

Grazie questo aiutato. Ho avuto il codice in viewDidLoad in cui ha cercato di visualizzare una finestra di dialogo alla fine.
ArdenDev,

Ricevo questo errore durante l'esecuzione di test di unità / integrazione in cui non eseguo test con animazioni.
mixtly87,

21

Nel mio caso, ho una sampleViewControllervista aggiunta come sottoview, quindi prova a presentare un popover dalla vista di sampleViewController(qui selfinvece UIViewControllerun'istanza):

[self.view addSubview:sampleViewController.view];

Il modo giusto dovrebbe essere sotto:

// make sure the vc has been added as a child view controller as well
[self addChildViewController:sampleViewController];
[self.view addSubview:sampleViewController.view];
[sampleViewController didMoveToParentViewController:self];

A proposito, questo funziona anche nel caso in cui presenti un popover da una cella tableview, devi solo assicurarti che il controller tableview sia stato aggiunto anche come controller vista figlio.


Inoltre chiama didMoveToParentViewController. Per favore controlla Aggiungi e rimuovi ChildViewController: gist.github.com/tomohisa/2897676
Jakehao

@jianzong, ricordo che non è necessario fare l'ultimo passo. Ad ogni modo, lasciami aggiungere, grazie per il suggerimento. :)
Kjuly,

Sì, funzionerà senza l'ultimo passaggio. Penso che lo scopo sia quello di informare parentViewController in modo che chiamerà alcuni metodi per fare qualcosa. :)
Jakehao,

2
funziona per me, sto usando la vista di un controller in un altro controller - (vista contenitore in modo programmatico), non ho aggiunto [self addChildViewController:sampleViewController];, ora ho aggiunto questo, grazie
anjnkmr

16

Penso che il problema sia che non hai una corretta gerarchia del controller di visualizzazione. Imposta il rootviewcontroller dell'app e quindi mostra le nuove visualizzazioni spingendo o presentando su di esse nuovi controller di visualizzazione. Consenti a ciascun controller di visualizzazione di gestire le proprie visualizzazioni. Solo i controller di visualizzazione contenitore, come tabbarviewcontroller, dovrebbero mai aggiungere altre visualizzazioni di controller di visualizzazione alle proprie visualizzazioni. Leggi la guida alla programmazione dei controller di visualizzazione per ulteriori informazioni su come utilizzare correttamente i controller di visualizzazione. https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/


14

Swift 3

Per chiunque inciampare su questo, ecco la risposta rapida.

self.parent?.present(viewController, animated: true, completion: nil)

9

Ho quasi lo stesso problema. Il motivo era che ho provato a presentare un "alcuni" controller su un altro e dopo che l'animazione era stata completata, ho impostato il controller presentato come root. Dopo questa operazione tutti gli altri controller che presentano mi portano all'avvertimento: "La presentazione dei controller di vista su controller di vista separati è sconsigliata ". E risolvo questo avviso solo impostando "alcuni" controller come root senza alcuna presentazione all'inizio.

Rimosso:

[[self rootController] presentViewController:controller animated:YES completion:^{

       [self window].rootViewController = controller;

       [[self window] makeKeyAndVisible];}];

Crea come root senza alcuna presentazione:

 [[self window] setRootViewController:controller];

1
Questo era esattamente il mio problema. Stavo cercando di presentarlo con un UIModalTransitionStyleCrossDissolve e quindi renderlo rootViewController. Successivamente, tutte le altre presentazioni non hanno funzionato con il messaggio di avviso fornito. Basta impostarlo come rootViewcontroller senza animazione ha fatto il trucco. Grazie!
Bernardo Oliveira

7

Una delle soluzioni a questo è se hai un controller di visualizzazione figlio. Quindi, devi semplicemente presentare un controller di visualizzazione sul suo genitore

[self.parentViewController presentViewController:viewController animated:YES completion:nil];

E per eliminare usa lo stesso controller di vista

[self dismissViewControllerAnimated:YES completion:nil];

Questa soluzione perfetta funziona per me.


7

Utilizzare [self.navigationController presentViewController:xxx animated:YES completion:nil]in iOS 8.


5

Prova questo codice

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:<your ViewController object>];

[self.view.window.rootViewController presentViewController:navigationController animated:YES completion:nil];

4

Prova a presentare TabBarControllerse si tratta di TabBarControllerun'app basata.

[self.tabBarController presentViewController:viewController animated:YES completion:nil];

La ragione potrebbe essere selffiglia di TabBarControllere stai provando a presentare da a ChildViewController.


4

Sì, ho anche riscontrato lo stesso messaggio di avviso durante la visualizzazione di un controller di avviso che era in un'altra vista. In seguito l'ho evitato presentando il controller di avviso dal controller della vista padre come di seguito:

[self.parentViewController presentViewController:alertController animated:YES completion:nil];

3

è necessario aggiungere il controller della vista che presenterà il nuovo controller come figlio del controller della vista padre.

Supponiamo che tu abbia il tuo MainViewController, quindi aggiungi un nuovo controller chiamato controllerA e quindi desideri presentare un nuovo controller chiamato controllerB dal controllerA

devi scrivere qualcosa del genere:

[self addChildViewController:controllerA]; //self is yourMainViewController
[self.view addsubView:controllerA.view]; 

e all'interno del controllerA è possibile presentare il nuovo controller senza avvisi

[self presentViewController:controllerB animated:YES completion:nil]; //self is controllerA

3

In Swift 4.1 e Xcode 9.4.1

La soluzione è

DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

Se scrivi così sto ricevendo lo stesso errore

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
    })
alert.addAction(defaultAction)

present(alert, animated: true, completion: nil) 

Ricevo lo stesso errore

Presenting view controllers on detached view controllers is discouraged <MyAppName.ViewController: 0x7fa95560Z070>.

La soluzione completa è

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
     })
alert.addAction(defaultAction)
//Made Changes here    
DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

Eseguirlo attraverso DispatchQueue in questo modo ha funzionato per me. Sto facendo un performSegue a un controller di visualizzazione modale, chiamato da viewDidLoad sul mio controller di prima visualizzazione (una schermata introduttiva al primo avvio per orientare i nuovi utenti). Stava caricando bene, ma generando l'avvertimento. L'avvolgimento della chiamata performSegue nella chiamata asincrona DispatchQueue elimina l'avviso. Grazie!
Grant Neufeld,

1

Assicurati di disporre di un controller di visualizzazione radice per iniziare. Puoi impostarlo didFinishLaunchingWithOptions.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [window setRootViewController:viewController];
}

1

Molte ragioni per questo avviso. Il mio è perché ho un seguito collegato da un ViewController ad un altro che verrà presentato in modo modale. Ma il ViewController da me presentato viene generato dinamicamente da un PageViewController. Ecco perché è staccato nello Storyboard. La mia app non andrà in crash a causa sua; ma vorrei mettere a tacere l'avvertimento.


1

Ho raggiunto questo thread in cui ho una barra di navigazione personalizzata e stavo chiamando un AlertViewController attraverso di essa.

Ho dovuto aggiungerlo da bambino al mio controller della vista principale. Quindi potrei chiamare presentarlo senza alcun preavviso.

Devi aggiungere il tuo Zoomed Image View Controllercome figlio del ViewController principale.

(per esempio)

[self addChildViewController:ZoomedImageViewController];

Quindi sarai in grado di chiamare ZoomedImageViewController

[self presentViewController:ZoomedImageViewController];

1

Molte risposte sono giuste.

  • Verifica che il tuo presentatoreViewController abbia parentViewController o no.
  • In caso contrario, aggiungilo in un punto da aggiungere
  • altrimenti, controlla che parentViewController abbia parentViewController in modo ricorsivo finché ogni viewController ha parent

Questo problema si è verificato quando il mio collega ha aggiunto un AViewController a BViewController. In qualche modo, ha semplicemente aggiunto la vista di AViewController alla vista di BViewController.

Risolto da aggiungere bViewController.addChild (aViewController)


1
Grazie! l'aggiunta di addChild nel mio blocco di completamento Hero.shared.transition ha risolto completamente il mio problema.
landnbloc

0

Dipende se vuoi mostrare il tuo avviso o qualcosa di simile in qualsiasi tipo di UIViewController.

È possibile utilizzare questo esempio di codice:

UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Example" preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil];

[alert addAction:cancelAction];


[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alert animated:true completion:nil];

Con il tuo codice, non funziona e fornisce questo registroAttempt to present <UIAlertController: 0x7fc01a1eb600> on <ViewController: 0x7fc019821e00> whose view is not in the window hierarchy!
Naveed Abbas,
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.