Warnung: - Es wird davon abgeraten, Ansichts-Controller auf getrennten Ansichts-Controllern darzustellen

180

In meiner App verwende ich einen Navigationscontroller. In einigen Ansichten verwende ich später, presentViewControllerum ein gezoomtes Bild anzuzeigen . Außerdem benutze ich kein Storyboard oder keine Feder.

Ich erhalte diesen Fehler nur in iOS 7. Es funktioniert gut in iOS 6 und früher:

Es wird davon abgeraten, View Controller auf getrennten View Controllern zu präsentieren

Gagan Joshi
quelle
Ich habe es noch nicht herausgefunden. Aber in meiner App weise ich window.rootviewcontroller keinen Viewcontroller zu. Ich füge Ansicht zum Fenster hinzu. Vielleicht ist das der Grund für mich. aber nicht sicher ...
Gagan Joshi
@GaganJoshi Der oben erwähnte Grund ist möglicherweise nicht die Ursache. Sogar ich stehe vor dem gleichen Problem. Und in unserem Projekt weise ich window.rootviewcontroller einen View Controller zu.
Rajesh
1
Ich denke, die anderen Kommentare beziehen sich korrekt auf etwas über den rootViewController und die Fensterverbindung. Ich habe das noch nicht ganz herausgefunden, aber ich konnte das Problem umgehen, indem ich den Controller direkt auf dem rootViewController anstatt auf dem Navigationscontroller oder einem seiner untergeordneten Elemente präsentierte.
Rich Waters
Azaxis hat es bekommen: stackoverflow.com/a/31877722/5306470
Daniel Springer

Antworten:

207

Um zu vermeiden, dass die Warnung in einer Push-Navigation angezeigt wird, können Sie direkt Folgendes verwenden:

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

Und wenn in Ihrem Modal View Controller alles fertig ist, können Sie einfach anrufen:

[self dismissViewControllerAnimated:YES completion:nil];

cdescours
quelle
Ich präsentiere die Bildauswahl mit diesem Zeilencode "[self.view.window.rootViewController presentViewController: viewController animiert: JA Vervollständigung: null];" Poicker-Ansicht mit dieser Zeile kann jedoch nicht geschlossen werden. Jede alternative Option für Entlassungscontroller
kb920
@keyurbhalodiya Sie müssen die Methode descViewController aus modalView aufrufen, damit sie funktioniert. Wenn Sie also eine Ansicht mit dem Namen viewB aus einer viewA mit [viewA.window.rootViewController presentViewController: viewB] angezeigt haben, müssen Sie in viewB beispielsweise eine Schaltfläche hinzufügen, die einer benutzerdefinierten Aktion zugeordnet ist, die [self entlassenViewControllerAnimated] aufruft. Ist es klarer?
Cdescours
11
Viewcontroller wird in iOS 8 nicht angezeigt.
Rajesh Maurya
1
für iOS 8: [self.view.window.rootViewController.navigationController
Fede Cugliandolo
31
mit self.navigationControllerhat es für mich getan.
Brandon Zacharie
62

Der Grund für diese Warnung ist, dass ich einen Ansichts-Controller über einer kleinen Ansicht präsentierte, die keine Ansicht in voller Größe ist. Unten ist das Bild meines Projekts angegeben. Klicken Sie oben auf vier Optionen. Der Benutzer navigiert zu einer anderen Ansicht des untergeordneten Ansichtscontrollers (funktioniert wie der tabViewcontroller). Der Childviewcontroller enthält jedoch eine Ansicht von geringer Größe. Wenn wir also eine Ansicht von childviewcontroller präsentieren, wird diese Warnung ausgegeben.

Hauptdetailansicht

Um dies zu vermeiden, können Sie eine Ansicht des übergeordneten Elements von childviewcontroller anzeigen

  [self.parentViewController presentViewController:viewController animated:YES completion:nil];
Gagan Joshi
quelle
1
[self.view.window.rootViewController.navigationController pushViewController: YOUR_VIEW_CONTROLER animiert: YES];
Fede Cugliandolo
1
"präsentierte einen Ansichts-Controller über einer kleinen Ansicht, die keine Ansicht in voller Größe ist." ... GENAU. Gute Arbeit.
Fattie
59

Warten Sie auf viewDidAppear():

Dieser Fehler kann auch auftreten, wenn Sie versuchen, den Ansichts-Controller anzuzeigen, bevor die Ansicht tatsächlich angezeigt wurde, z. B. die Ansicht in viewWillAppear()oder früher. Versuchen Sie, danach viewDidAppear()oder darin eine andere Ansicht darzustellen.

Azaxis
quelle
9
Mit anderen Worten, präsentieren Sie keine View Controller in viewDidLoad(), Leute! Ich habe diesen Fehler so oft gemacht ...
T Blank
Danke das hat geholfen. Ich hatte Code in viewDidLoad, in dem versucht wurde, am Ende einen Dialog anzuzeigen.
ArdenDev
Ich erhalte diesen Fehler, wenn ich Unit- / Integrationstests ausführe, bei denen ich nicht mit Animationen teste.
Mixtly87
21

In meinem Fall habe ich sampleViewControllerdie Ansicht von a als Unteransicht hinzugefügt und dann versucht, ein Popover aus der Ansicht von sampleViewController(hier selfstattdessen eine UIViewControllerInstanz) darzustellen :

[self.view addSubview:sampleViewController.view];

Der richtige Weg sollte unten sein:

// 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];

Übrigens funktioniert dies auch für den Fall, dass ein Popover aus einer Tabellenansichtszelle angezeigt wird. Sie müssen lediglich sicherstellen, dass der Tabellenansichts-Controller auch als untergeordneter Ansichts-Controller hinzugefügt wurde.

Kjuly
quelle
Rufen Sie außerdem didMoveToParentViewController auf. Bitte überprüfen Sie Hinzufügen und Entfernen von ChildViewController: gist.github.com/tomohisa/2897676
Jakehao
@jianzong Ich erinnere mich, dass es nicht nötig ist, den letzten Schritt zu tun. Wie auch immer, lassen Sie es mich hinzufügen, danke für den Vorschlag. :)
Kjuly
Ja, es wird ohne den letzten Schritt funktionieren. Ich denke, der Zweck ist es, den parentViewController so zu informieren, dass er einige Methoden aufruft, um etwas zu tun. :)
Jakehao
2
es funktioniert für mich, ich verwende die Ansicht eines Controllers in einem anderen Controller - (Containeransicht programmgesteuert), ich habe nicht hinzugefügt [self addChildViewController:sampleViewController];, jetzt habe ich dies hinzugefügt, danke
anjnkmr
16

Ich denke, das Problem ist, dass Sie keine richtige View-Controller-Hierarchie haben. Stellen Sie den Rootviewcontroller der App ein und zeigen Sie dann neue Ansichten an, indem Sie neue Viewcontroller darauf drücken oder präsentieren. Lassen Sie jeden Ansichts-Controller seine Ansichten verwalten. Nur Container-View-Controller wie der Tabbarviewcontroller sollten jemals andere View-Controller-Ansichten zu ihren eigenen Ansichten hinzufügen. Lesen Sie die Programmieranleitung für View Controller, um mehr über die ordnungsgemäße Verwendung von View Controllern zu erfahren. https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/

Daniel Ytterbrink
quelle
14

Swift 3

Für alle, die darüber stolpern, ist hier die schnelle Antwort.

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

Ich habe fast das gleiche Problem. Der Grund war, dass ich versucht habe, "einige" Controller auf einem anderen zu präsentieren, und nachdem die Animation abgeschlossen war, habe ich den präsentierten Controller als root festgelegt. Nach diesem Vorgang bringen mich alle weiteren Controller zur Warnung: "Das Präsentieren von View-Controllern auf getrennten View-Controllern wird nicht empfohlen. " Und ich löse diese Warnung, indem ich nur "einige" Controller als root ohne Präsentation am Anfang einstelle.

Entfernt:

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

       [self window].rootViewController = controller;

       [[self window] makeKeyAndVisible];}];

Machen Sie einfach als Root ohne Präsentation:

 [[self window] setRootViewController:controller];
Averem
quelle
1
Das war genau mein Problem. Ich habe versucht, es mit einem UIModalTransitionStyleCrossDissolve zu präsentieren und es dann zu rootViewController zu machen. Danach schlugen alle anderen Präsentationen mit der angegebenen Warnmeldung fehl. Nur den RootViewcontroller ohne Animation festzulegen, hat den Trick getan. Vielen Dank!
Bernardo Oliveira
7

Eine der Lösungen hierfür ist, wenn Sie einen Childviewcontroller haben. Sie präsentieren also einfach den Viewcontroller auf dem übergeordneten Element, indem Sie ihn angeben

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

Verwenden Sie zum Entlassen denselben Entlassungs-Controller.

[self dismissViewControllerAnimated:YES completion:nil];

Dies ist die perfekte Lösung für mich.

Gagan Joshi
quelle
7

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

Tao Fang
quelle
5

Versuchen Sie diesen Code

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

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

Versuchen Sie zu präsentieren, TabBarControllerob es sich um eine TabBarControllerbasierte App handelt.

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

Grund könnte sein, selfist ein Kind von TabBarControllerund Sie versuchen, von einem zu präsentieren ChildViewController.

Warif Akhand Rishi
quelle
4

Ja, ich habe auch dieselbe Warnmeldung erhalten, als ich einen Alert-Controller angezeigt habe, der sich in einer anderen Ansicht befand. Später habe ich dies vermieden, indem ich den Alert-Controller vom übergeordneten View-Controller wie folgt dargestellt habe:

[self.parentViewController presentViewController:alertController animated:YES completion:nil];
Sivasagar Palakurthy
quelle
3

Sie müssen den Ansichts-Controller hinzufügen, der den neuen Controller als untergeordnetes Element des übergeordneten Ansichts-Controllers darstellt.

Angenommen, Sie haben Ihren MainViewController, fügen dann einen neuen Controller namens controllerA hinzu und möchten dann einen neuen Controller namens controllerB von controllerA präsentieren

du musst so etwas schreiben:

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

und innerhalb von controllerA können Sie den neuen Controller ohne Warnungen präsentieren

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

In Swift 4.1 und Xcode 9.4.1

Die Lösung ist

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

Wenn ich so schreibe, bekomme ich den gleichen Fehler

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) 

Ich erhalte den gleichen Fehler

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

Komplettlösung ist

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)
})
iOS
quelle
Das Ausführen durch DispatchQueue hat bei mir funktioniert. Ich mache ein performSegue für einen modalen Ansichts-Controller, der von viewDidLoad auf meinem ersten Ansichts-Controller aufgerufen wird (ein Intro-Bildschirm zum ersten Start, um neue Benutzer zu orientieren). Es wurde gut geladen, aber die Warnung wurde generiert. Durch das Umschließen des performSegue-Aufrufs in den asynchronen DispatchQueue-Aufruf wird die Warnung entfernt. Vielen Dank!
Grant Neufeld
1

Stellen Sie zunächst sicher, dass Sie über einen Root View Controller verfügen. Sie können es einstellen didFinishLaunchingWithOptions.

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

Viele Gründe für diese Warnung. Meins ist, weil ich einen Übergang von einem ViewController zu einem anderen habe, der modal dargestellt wird. Der ViewController, aus dem ich präsentiere, wird jedoch dynamisch von einem PageViewController generiert. Aus diesem Grund wird es im Storyboard getrennt. Meine App wird deswegen nicht abstürzen. aber ich möchte die Warnung zum Schweigen bringen.

Lee Probert
quelle
1

Ich habe diesen Thread erreicht, in dem ich eine benutzerdefinierte Navigationsleiste habe, und habe über diesen einen AlertViewController aufgerufen.

Ich musste es als Kind meinem Hauptansichts-Controller hinzufügen. Dann könnte ich es ohne Vorwarnung präsentieren.

Sie sollten Ihre Zoomed Image View Controllerals untergeordnetes Element des Haupt-ViewControllers hinzufügen.

(z.B)

[self addChildViewController:ZoomedImageViewController];

Dann können Sie Ihren ZoomedImageViewController aufrufen

[self presentViewController:ZoomedImageViewController];
Naveed Abbas
quelle
1

Viele Antworten sind richtig.

  • Überprüfen Sie, ob Ihr PresentingViewController über ParentViewController verfügt oder nicht.
  • Wenn nein, fügen Sie es an einer Stelle hinzu, an der es hinzugefügt werden soll
  • Überprüfen Sie andernfalls, ob parentViewController über parentViewController verfügt, bis jeder viewController übergeordnet ist

Dieses Problem ist mir passiert, als mein Kollege BViewController einen AViewController hinzufügte. Irgendwie fügt er einfach die Ansicht des AViewControllers zur Ansicht des BViewControllers hinzu.

Behoben durch Hinzufügen von bViewController.addChild (aViewController)

Jerome Li
quelle
1
Danke dir! Das Hinzufügen von addChild in meinem Hero.shared.transition-Abschlussblock hat mein Problem vollständig gelöst.
Landblock
0

Es hängt davon ab, ob Sie Ihre Warnung oder ähnliches in einem beliebigen UIViewController anzeigen möchten.

Sie können dieses Codebeispiel verwenden:

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];
Fabio
quelle
Mit Ihrem Code funktioniert es nicht und gibt dieses ProtokollAttempt to present <UIAlertController: 0x7fc01a1eb600> on <ViewController: 0x7fc019821e00> whose view is not in the window hierarchy!
Naveed Abbas