Versuchen Sie, UIViewController auf UIViewController darzustellen, dessen Ansicht nicht in der Fensterhierarchie enthalten ist

599

Ich habe gerade angefangen, Xcode 4.5 zu verwenden und habe diesen Fehler in der Konsole erhalten:

Warnung: Versuchen Sie, <finishViewController: 0x1e56e0a0> auf <ViewController: 0x1ec3e000> anzuzeigen, dessen Ansicht nicht in der Fensterhierarchie enthalten ist!

Die Ansicht wird noch angezeigt und alles in der App funktioniert einwandfrei. Ist das etwas Neues in iOS 6?

Dies ist der Code, mit dem ich zwischen Ansichten wechsle:

UIStoryboard *storyboard = self.storyboard;
finishViewController *finished = 
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];

[self presentViewController:finished animated:NO completion:NULL];
Kyle Goslan
quelle
3
Ich habe genau das gleiche Problem, außer dass ich versuche, presentViewController:animated:completioneinen Navigationscontroller aufzurufen . Tun Sie dies im App-Delegaten?
Tarnfeld
Nein, ich mache es von einem View Controller zum anderen. Haben Sie Lösungen gefunden?
Kyle Goslan
Das gleiche Problem bei einem Teil des Codes, der vor der Verwendung von Xcode 4.5 immer funktioniert hat. Ich präsentiere einen UINavigationController, aber auch dies hat immer vorher funktioniert.
Emanuele Fumagalli
Ich habe das gleiche Problem, nicht gelöst. Dies geschieht vom App-Delegaten aus, und der rootviewcontroller, der "presentViewController" aufruft, ist ein UITabBarController.
Darksider
3
Wenn Sie diese Methode aufrufen, bevor Sie makeKeyAndVisible aufrufen, verschieben Sie sie danach
mike_haney

Antworten:

1296

Woher rufen Sie diese Methode auf? Ich hatte ein Problem, bei dem ich versuchte, einen Modal View Controller innerhalb der viewDidLoadMethode zu präsentieren. Die Lösung für mich bestand darin, diesen Aufruf auf die viewDidAppear:Methode zu verschieben.

Meine Vermutung ist , dass die Ansicht des View - Controller ist nicht in der Ansichtshierarchie des Fensters an dem Punkt , dass es geladen worden ist (wenn die viewDidLoadNachricht gesendet wird), aber es ist in der Hierarchie - Fenster , nachdem sie dargestellt worden ist (wenn die viewDidAppear:Nachricht gesendet wird ) .


Vorsicht

Wenn Sie einen Anruf tätigen zu tun presentViewController:animated:completion:in der viewDidAppear:Sie in ein Problem laufen kann , wodurch die modal - View - Controller immer vorgestellt wird , wenn die Sicht erscheint die View - Controller (das macht Sinn!) Und so die modale View - Controller präsentiert wird nie weggehen .. .

Möglicherweise ist dies nicht der beste Ort, um den Modal View Controller zu präsentieren, oder es muss ein zusätzlicher Status beibehalten werden, der es dem Presenting View Controller ermöglicht, zu entscheiden, ob er den Modal View Controller sofort präsentieren soll oder nicht.

James Bedford
quelle
6
@James Sie haben Recht, die Ansicht befindet sich anscheinend erst in der Hierarchie, nachdem viewWillAppear aufgelöst und viewDidAppear aufgerufen wurde. Wenn dies meine Frage wäre, würde ich diese Antwort akzeptieren;)
Matt Mc
6
@ James Danke. Die Verwendung von ViewDidAppear löste das Problem auch für mich. Macht Sinn.
Ali
44
Ich wünschte, ich könnte dies zweimal positiv bewerten. Ich hatte gerade dieses Problem und kam zu dem Thread, um festzustellen, dass ich bereits das letzte Mal, als ich das sah, upvoted hatte.
Schrockwell
7
Beachten Sie, dass beim Ändern der VC in viewDidAppear dadurch ein Übergang mit Animation ausgeführt wird. Verursacht einen Blitz / eine Anzeige des Hintergrunds.
Vincent
2
Ja, der Trick ist das animierte viewWillAppear: (BOOL). Eine weitere wichtige Sache, die Sie in der Methode als Super bezeichnen müssen, ist [super viewDidAppear: animiert]; ohne das funktioniert es nicht.
BootMaker
66

Eine weitere mögliche Ursache:

Ich hatte dieses Problem, als ich versehentlich zweimal denselben View Controller präsentierte. (Einmal mit performSegueWithIdentifer:sender:dem wurde aufgerufen, als die Taste gedrückt wurde, und ein zweites Mal mit einem direkt mit der Taste verbundenen Segue).

Tatsächlich feuerten zwei Segues gleichzeitig und ich bekam den Fehler: Attempt to present X on Y whose view is not in the window hierarchy!

Chris Nolet
quelle
4
Ich hatte den gleichen Fehler, und Ihre Antwort hier half mir herauszufinden, was los war. Es war in der Tat dieser Fehler. Er wurde wegen Ihnen behoben, Sir. Danke, +1
Samouray,
1
Ich habe den alten Abschnitt gelöscht und VC mit VC verbunden. Gibt es eine Möglichkeit, den Button mit dem StoryBoard mit dem VC zu verbinden, weil dieser Weg für mich immer wieder Fehler macht?
MCB
Ich hatte den gleichen Fehler, Ihre Antwort hat mein Problem gelöst, danke für Ihre Aufmerksamkeit. Mit freundlichen Grüßen.
Iamburak
1
lol, aus Versehen habe ich auch zwei VCs erstellt: von button und performSegue, danke für den Tipp !!!
Borzh
1
In meinem Fall habe ich in present(viewController, animated: true, completion: nil)einer Schleife angerufen .
Samo
38

viewWillLayoutSubviewsund viewDidLayoutSubviews(iOS 5.0+) können für diesen Zweck verwendet werden. Sie werden früher als viewDidAppear aufgerufen.

Jonny
quelle
3
Trotzdem werden sie auch bei anderen Gelegenheiten verwendet, daher denke ich, dass sie im "Leben" einer Ansicht mehrmals aufgerufen werden könnten.
Jonny
Es ist auch nicht das, wofür die Methoden sind - wie der Name schon sagt. viewDidAppear ist korrekt. Es ist eine gute Idee, sich über den Lebenszyklus der Ansicht zu informieren.
Tooluser
Dies ist die beste Lösung. In meinem Fall führt die Präsentation in viewDidAppear dazu, dass der View-Controller in Sekundenbruchteilen angezeigt wird, bevor das Modal geladen wird, was nicht akzeptabel ist.
TMilligan
Diese Antwort hat für mich am besten funktioniert, als ich versucht habe, eine Warnung anzuzeigen. Die Warnung wird nicht angezeigt, wenn ich sie in viewDidLoad und viewWillAppear einfüge.
uplearnedu.com
26

Verwenden Sie zum Anzeigen einer Unteransicht zur Hauptansicht den folgenden Code

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController presentViewController:composeViewController animated:YES completion:nil];

Verwenden Sie den folgenden Code, um eine Unteransicht aus der Hauptansicht zu entfernen

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController dismissViewControllerAnimated:YES completion:nil];
abdul sathar
quelle
Arbeitete auch für mich
Aziz Javed
17

Dieses Problem trat auch auf, als ich versuchte, ein UIViewControllerIn zu präsentieren viewDidLoad. James Bedfords Antwort funktionierte, aber meine App zeigte zuerst 1 oder 2 Sekunden lang den Hintergrund.

Nach einigen Recherchen habe ich einen Weg gefunden, dies mit dem zu lösen addChildViewController.

- (void)viewDidLoad
{
    ...
    [self.view addSubview: navigationViewController.view];
    [self addChildViewController: navigationViewController];
    ...
}
sunkehappy
quelle
9
Ich denke, Sie fehlen [navigationViewController didMoveToParentViewController: self]
foFox
2
Ich habe Ihren Code zusammen mit dem Vorschlag von foFox ausprobiert, und wenn ich ihn von seinem übergeordneten Code entferne, wird er nicht verschwinden. Lololol. Immer noch ohne Fix stecken.
Logicsaurus Rex
Arbeitet in Swift3.1
Kang Byul
@sunkehappy über zwei Zeilen, die vor dem Presentviewcontroller verwendet werden sollen, aber es ist abgestürzt, warum?
Iyyappan Ravi
14

Wahrscheinlich hast du wie ich eine falsche Wurzel viewController

Ich möchte ein ViewControllerin einem anzeigennon-UIViewController Kontext ,

Ich kann solchen Code also nicht verwenden:

[self presentViewController:]

Also bekomme ich einen UIViewController:

[[[[UIApplication sharedApplication] delegate] window] rootViewController]

Aus irgendeinem Grund (logischer Fehler) ist das rootViewControlleretwas anderes als erwartet (normal UIViewController). Dann korrigiere ich den Fehler, ersetze ihn rootViewControllerdurch a UINavigationControllerund das Problem ist weg.

Sanbrother
quelle
8

TL; DR Sie können nur 1 rootViewController und den zuletzt vorgestellten haben. Versuchen Sie also nicht, dass ein Viewcontroller einen anderen Viewcontroller präsentiert, wenn dieser bereits einen nicht entlassenen präsentiert.

Nachdem ich einige meiner eigenen Tests durchgeführt habe, bin ich zu einem Schluss gekommen.

Wenn Sie einen rootViewController haben, auf dem Sie alles präsentieren möchten, kann dieses Problem auftreten.

Hier ist mein rootController-Code (offen ist meine Verknüpfung zum Präsentieren eines Viewcontrollers aus dem Stammverzeichnis).

func open(controller:UIViewController)
{
    if (Context.ROOTWINDOW.rootViewController == nil)
    {
        Context.ROOTWINDOW.rootViewController = ROOT_VIEW_CONTROLLER
        Context.ROOTWINDOW.makeKeyAndVisible()
    }

    ROOT_VIEW_CONTROLLER.presentViewController(controller, animated: true, completion: {})
}

Wenn ich zweimal hintereinander aufrufe (unabhängig von der verstrichenen Zeit), funktioniert dies beim ersten Öffnen einwandfrei, beim zweiten Öffnen jedoch NICHT. Der zweite offene Versuch führt zu dem obigen Fehler.

Wenn ich jedoch die zuletzt präsentierte Ansicht schließe und dann open aufrufe, funktioniert dies einwandfrei, wenn ich open erneut aufrufe (auf einem anderen Viewcontroller).

func close(controller:UIViewController)
{
    ROOT_VIEW_CONTROLLER.dismissViewControllerAnimated(true, completion: nil)
}

Ich bin zu dem Schluss gekommen, dass sich der rootViewController nur des MOST-RECENT-CALL in der Ansichtshierarchie befindet (auch wenn Sie ihn nicht geschlossen oder eine Ansicht entfernt haben). Ich habe versucht, mit allen Loader-Aufrufen zu spielen (viewDidLoad, viewDidAppear und verzögerte Versandanrufe), und ich habe festgestellt, dass ich es nur zum Laufen bringen kann, wenn ich NUR vom obersten View-Controller anwesend bin.

Aggressor
quelle
Dies scheint ein weitaus häufigeres Problem zu sein als die vielen Antworten, die Ihre Stimmen abgegeben haben. Leider war dies äußerst hilfreich
Rayepps
Ja, alles schön und gut, aber was ist die Lösung ... Ich habe einen Hintergrund-Worker-Thread, der zu einem Server geht und Storyboards links rechts und mittig anzeigt, und die gesamte Methodik ist falsch. Es ist schrecklich. Was ein Kinderspiel sein sollte, ist absolut a Witz, weil alles, was ich tun möchte, im Hintergrund-Thread ist: wait wait decide push screen to frontund es ist UNMÖGLICH, ist IOS ????
Herr Heelis
5

Mein Problem war, dass ich die Segue-In UIApplicationDelegate- didFinishLaunchingWithOptionsMethode durchführte, bevor ich makeKeyAndVisible()das Fenster anrief.

Adam Johns
quelle
Wie? Kannst du das näher erläutern? Ich stehe vor dem gleichen Problem. dies ist mein Code initialViewControlleripad lassen: UIViewController = mainStoryboardIpad.instantiateViewController (withIdentifier: "SplashController") als UIViewController self.window .rootViewController = initialViewControlleripad self.window .makeKeyAndVisible ()?
shahtaj khalid
4

In meiner Situation war ich nicht in der Lage, meine in eine Klassenüberschreibung zu versetzen. Also, hier ist was ich habe:

let viewController = self // I had viewController passed in as a function,
                          // but otherwise you can do this


// Present the view controller
let currentViewController = UIApplication.shared.keyWindow?.rootViewController
currentViewController?.dismiss(animated: true, completion: nil)

if viewController.presentedViewController == nil {
    currentViewController?.present(alert, animated: true, completion: nil)
} else {
    viewController.present(alert, animated: true, completion: nil)
}
George_E
quelle
3

Ich hatte das gleiche Problem. Ich musste einen Navigationscontroller einbetten und den Controller durch ihn präsentieren. Unten ist der Beispielcode.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UIImagePickerController *cameraView = [[UIImagePickerController alloc]init];
    [cameraView setSourceType:UIImagePickerControllerSourceTypeCamera];
    [cameraView setShowsCameraControls:NO];

    UIView *cameraOverlay = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 768, 1024)];
    UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"someImage"]];
    [imageView setFrame:CGRectMake(0, 0, 768, 1024)];
    [cameraOverlay addSubview:imageView];

    [cameraView setCameraOverlayView:imageView];

    [self.navigationController presentViewController:cameraView animated:NO completion:nil];
//    [self presentViewController:cameraView animated:NO completion:nil]; //this will cause view is not in the window hierarchy error

}
ruhen
quelle
3

Wenn Sie ein AVPlayer-Objekt mit abgespieltem Video haben, müssen Sie zuerst das Video anhalten.

Vlad
quelle
Ich meine, das Video sollte zuerst gestoppt / angehalten werden.
Vlad
Eigentlich hat mir das geholfen, es hat mich danach zu diesem stackoverflow.com/questions/20746413/…
Omar N Shamali
3

Ich hatte das gleiche Problem. Das Problem war, dass performSegueWithIdentifier durch eine Benachrichtigung ausgelöst wurde, sobald ich die Benachrichtigung in den Hauptthread legte, war die Warnmeldung verschwunden.

rot
quelle
3

Es funktioniert gut, versuchen Sie es. Verknüpfung

UIViewController *top = [UIApplication sharedApplication].keyWindow.rootViewController;
[top presentViewController:secondView animated:YES completion: nil];
Vijay
quelle
3

Für den Fall, dass es jemandem hilft, war mein Problem extrem dumm. Völlig meine Schuld natürlich. Eine Benachrichtigung löste eine Methode aus, die das Modal aufrief. Aber ich habe die Benachrichtigung nicht richtig entfernt, sodass ich irgendwann mehr als eine Benachrichtigung hatte, sodass das Modal mehrmals aufgerufen wurde. Nachdem Sie das Modal einmal aufgerufen haben, befindet sich der Viewcontroller, der es aufruft, natürlich nicht mehr in der Ansichtshierarchie. Deshalb sehen wir dieses Problem. Meine Situation verursachte auch eine Reihe anderer Probleme, wie Sie es erwarten würden.

Zusammenfassend lässt sich also sagen , dass das Modal nicht mehr als einmal aufgerufen wird .

HotFudgeSunday
quelle
3

Am Ende habe ich einen solchen Code gefunden, der für mich endlich funktioniert (Swift), wenn man bedenkt, dass Sie einige viewControllervon praktisch überall anzeigen möchten . Dieser Code stürzt offensichtlich ab, wenn kein rootViewController verfügbar ist. Das ist das offene Ende. Es beinhaltet auch nicht den normalerweise erforderlichen Wechsel zum UI-Thread mit

dispatch_sync(dispatch_get_main_queue(), {
    guard !NSBundle.mainBundle().bundlePath.hasSuffix(".appex") else {
       return; // skip operation when embedded to App Extension
    }

    if let delegate = UIApplication.sharedApplication().delegate {
        delegate.window!!.rootViewController?.presentViewController(viewController, animated: true, completion: { () -> Void in
            // optional completion code
        })
    }
}
igraczech
quelle
Übrigens, um zu verstehen, woher ich diese Methode aufrufe ... es ist die ansonsten UI-freie SDK-Bibliothek, die in bestimmten (nicht genannten) Fällen eine eigene Benutzeroberfläche über Ihrer App anzeigt.
igraczech
Sie werden abstürzen und brennen, wenn jemand beschließt, Ihr SDK in eine App mit einer Erweiterung einzubetten. Übergeben Sie einen UIViewController zum Missbrauch an Ihre SDK-Init-Methode (n).
Anton Tropashko
Du bist wahr, Anton. Dieser Code wurde geschrieben, als keine Erweiterungen vorhanden waren und SDK in keiner dieser Erweiterungen verwendet wird. Ich habe eine Schutzklausel hinzugefügt, um diesen Randfall zu überspringen.
igraczech
3

Diese Art von Warnung kann bedeuten, dass Sie versuchen, Neues View Controllerdurch zu präsentieren, Navigation Controllerwährend dies Navigation Controllergerade ein anderes präsentiert View Controller. Um dies zu beheben, müssen Sie die aktuell zuerst präsentierte View Controllerund nach Fertigstellung die neue präsentieren. Eine andere Ursache für die Warnung kann sein, dass versucht wird, einen View Controlleranderen Thread als zu präsentieren main.

saltwat5r
quelle
3

Ich hatte ein ähnliches Problem mit Swift 4.2, aber meine Ansicht wurde nicht aus dem Ansichtszyklus dargestellt. Ich stellte fest, dass ich mehrere Abschnitte gleichzeitig präsentieren musste. Also habe ich dispatchAsyncAfter verwendet.

func updateView() {

 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in

// for programmatically presenting view controller 
// present(viewController, animated: true, completion: nil)

//For Story board segue. you will also have to setup prepare segue for this to work. 
 self?.performSegue(withIdentifier: "Identifier", sender: nil)
  }
}
Ashim Dahal
quelle
2

Ich habe es behoben, indem ich die start()Funktion innerhalb des dismissAbschlussblocks verschoben habe:

self.tabBarController.dismiss(animated: false) {
  self.start()
}

Start enthält zwei Aufrufe an self.present()einen für einen UINavigationController und einen für einenUIImagePickerController .

Das hat es für mich behoben.

Alper
quelle
1

Sie können diese Warnung auch erhalten, wenn Sie einen Übergang von einem Ansichtscontroller durchführen, der in einen Container eingebettet ist. Die richtige Lösung besteht darin, Segue vom übergeordneten Container und nicht vom View Controller des Containers zu verwenden.

Borzh
quelle
1

Müssen unter Zeile schreiben.

self.searchController.definesPresentationContext = true

anstatt

self.definesPresentationContext = true

in UIViewController

Coder_A_D
quelle
1

Mit Swift 3 ...

Eine andere mögliche Ursache dafür, die mir passiert ist, war ein Übergang von einer tableViewCell zu einem anderen ViewController im Storyboard. Ich habe auch verwendetoverride func prepare(for segue: UIStoryboardSegue, sender: Any?) {} wenn die Zelle angeklickt wurde.

Ich habe dieses Problem behoben, indem ich von ViewController zu ViewController gewechselt bin.

Devbot10
quelle
1

Ich hatte dieses Problem und die Hauptursache war das mehrfache Abonnieren eines Button-Click-Handlers (TouchUpInside).

Es wurde in ViewWillAppear abonniert, das mehrmals aufgerufen wurde, seit wir die Navigation hinzugefügt hatten, um zu einem anderen Controller zu wechseln und dann wieder dorthin zurückzukehren.

Wir s
quelle
1

Mir ist passiert, dass der Abschnitt im Storyboard irgendwie kaputt war . Das Löschen des Segues (und das erneute Erstellen des exakten Segues) löste das Problem.

vonox7
quelle
1

In Ihrem Hauptfenster wird es wahrscheinlich immer Zeiten mit Übergängen geben, die mit der Anzeige einer Warnung nicht kompatibel sind. Damit Sie jederzeit in Ihrem Anwendungslebenszyklus Warnungen anzeigen können, sollten Sie über ein separates Fenster verfügen, in dem Sie die Aufgabe ausführen können.

/// independant window for alerts
@interface AlertWindow: UIWindow

+ (void)presentAlertWithTitle:(NSString *)title message:(NSString *)message;

@end

@implementation AlertWindow

+ (AlertWindow *)sharedInstance
{
    static AlertWindow *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[AlertWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
    });
    return sharedInstance;
}

+ (void)presentAlertWithTitle:(NSString *)title message:(NSString *)message
{
    // Using a separate window to solve "Warning: Attempt to present <UIAlertController> on <UIViewController> whose view is not in the window hierarchy!"
    UIWindow *shared = AlertWindow.sharedInstance;
    shared.userInteractionEnabled = YES;
    UIViewController *root = shared.rootViewController;
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    alert.modalInPopover = true;
    [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        shared.userInteractionEnabled = NO;
        [root dismissViewControllerAnimated:YES completion:nil];
    }]];
    [root presentViewController:alert animated:YES completion:nil];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    self.userInteractionEnabled = NO;
    self.windowLevel = CGFLOAT_MAX;
    self.backgroundColor = UIColor.clearColor;
    self.hidden = NO;
    self.rootViewController = UIViewController.new;

    [NSNotificationCenter.defaultCenter addObserver:self
                                           selector:@selector(bringWindowToTop:)
                                               name:UIWindowDidBecomeVisibleNotification
                                             object:nil];

    return self;
}

/// Bring AlertWindow to top when another window is being shown.
- (void)bringWindowToTop:(NSNotification *)notification {
    if (![notification.object isKindOfClass:[AlertWindow class]]) {
        self.hidden = YES;
        self.hidden = NO;
    }
}

@end

Grundlegende Verwendung, die von Natur aus immer erfolgreich sein wird:

[AlertWindow presentAlertWithTitle:@"My title" message:@"My message"];
Cœur
quelle
1

Leider hat die akzeptierte Lösung für meinen Fall nicht funktioniert. Ich habe versucht, direkt nach dem Abwickeln von einem anderen View Controller zu einem neuen View Controller zu navigieren.

Ich fand eine Lösung, indem ich ein Flag verwendete, um anzuzeigen, welcher Abwicklungsabschnitt aufgerufen wurde.

@IBAction func unwindFromAuthenticationWithSegue(segue: UIStoryboardSegue) {
    self.shouldSegueToMainTabBar = true
}

@IBAction func unwindFromForgetPasswordWithSegue(segue: UIStoryboardSegue) {
    self.shouldSegueToLogin = true
}

Dann präsentieren Sie die gewünschte VC mit present(_ viewControllerToPresent: UIViewController)

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    if self.shouldSegueToMainTabBar {
        let mainTabBarController = storyboard.instantiateViewController(withIdentifier: "mainTabBarVC") as! MainTabBarController
        self.present(mainTabBarController, animated: true)
        self.shouldSegueToMainTabBar = false
    }
    if self.shouldSegueToLogin {
        let loginController = storyboard.instantiateViewController(withIdentifier: "loginVC") as! LogInViewController
        self.present(loginController, animated: true)
        self.shouldSegueToLogin = false
    }
}

Grundsätzlich kann ich mit dem obigen Code das Abwickeln von Login / SignUp VC abfangen und zum Dashboard navigieren oder die Abwicklungsaktion von Passwort vergessen VC abfangen und zur Anmeldeseite navigieren.

Fan Jin
quelle
1

Ich habe diesen Fehler behoben, indem ich den obersten Viewcontroller in einer Konstanten gespeichert habe, die sich während des Zyklus über rootViewController befindet:

if var topController = UIApplication.shared.keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }
    topController.present(controller, animated: false, completion: nil)
    // topController should now be your topmost view controller
}
Marek Baláž
quelle
1

Ich habe festgestellt, dass dieser Fehler nach der Aktualisierung von Xcode aufgetreten ist. Ich glaube, Swift 5 . Das Problem trat auf, als ich direkt nach dem Abwickeln eines View Controllers programmgesteuert einen Segue startete.

Die Lösung wurde gefunden, als ein verwandter Fehler behoben wurde. Der Benutzer konnte nun Segues durch Wischen auf der Seite abwickeln. Dies hat die Logik meines Programms gebrochen.

Dies wurde behoben, indem der Präsentationsmodus auf allen Ansichtssteuerungen von Automatisch auf Vollbild geändert wurde .

Sie können dies im Attributfenster im Interface Builder tun. In dieser Antwort erfahren Sie, wie Sie dies programmgesteuert tun.

Tim MB
quelle
0

Ich hatte gerade auch dieses Problem, aber es hatte nichts mit dem Timing zu tun. Ich habe einen Singleton verwendet, um Szenen zu verarbeiten, und ich habe ihn als Moderator festgelegt. Mit anderen Worten, "Selbst" war an nichts gebunden. Ich habe gerade seine innere "Szene" zum neuen Moderator gemacht und voila, es hat funktioniert. (Voila verliert seine Berührung, nachdem Sie seine Bedeutung gelernt haben, heh).

Also ja, es geht nicht darum, "auf magische Weise den richtigen Weg zu finden", sondern zu verstehen, wo Ihr Code steht und was er tut. Ich bin froh, dass Apple eine so einfache englische Warnmeldung gegeben hat, auch mit Emotionen. Ein großes Lob an den Apfelentwickler, der das getan hat !!

Stephen J.
quelle
0

Wenn andere Lösungen aus irgendeinem Grund nicht gut aussehen, können Sie diese gute alte workaroundDarstellung mit der Verzögerung von 0 wie folgt verwenden :

dispatch_after(0, dispatch_get_main_queue(), ^{
    finishViewController *finished = [self.storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];
    [self presentViewController:finished animated:NO completion:NULL];    
});

Ich habe zwar keine dokumentierte Garantie dafür gesehen, dass sich Ihr VC in der Ansichtshierarchie befindet, wenn die Ausführung des Versandblocks geplant ist, aber ich habe festgestellt, dass dies einwandfrei funktioniert.

Die Verwendung einer Verzögerung von z. B. 0,2 Sekunden ist ebenfalls eine Option. Und das Beste - auf diese Weise müssen Sie sich nicht mit booleschen Variablen anlegenviewDidAppear:

Dannie P.
quelle
2
Obwohl dies jetzt möglicherweise funktioniert, gibt es keine Garantie dafür, dass Apple das Verhalten ändert und dies in Zukunft bei Ihnen beeinträchtigt. Wenn Sie sich dann noch einmal Ihren Code ansehen, um zu versuchen, die Probleme erneut zu beheben, werden Sie sich fragen, warum Sie diesen scheinbar unnötigen Versand durchgeführt haben.
Cruinh
Der Versand mit 0 Zeit hat mich schon einige Male gerettet - manchmal funktionieren Dinge, die nur logisch funktionieren sollten, normalerweise nicht ohne sie. Machen Sie also einfach Kommentare für sich und andere, warum Sie nicht offensichtliche Dinge tun (nicht nur einen solchen Versand), und es sollte Ihnen gut gehen.
Dannie P
2
Sie hacken nur um das Problem herum und lösen es nicht.
Michael Peterson
0

Dies funktioniert, um einen beliebigen Ansichts-Controller anzuzeigen, wenn Sie einen Navigations-Controller zur Verfügung haben. self.navigationController? .present (MyViewController, animiert: true, Vervollständigung: nil) Außerdem kann ich auch Warnungen und Mail-Controller präsentieren.

Gurpreet Singh
quelle