672 Stimmen

Versuch, einen UIViewController auf einem UIViewController zu präsentieren, dessen Ansicht sich nicht in der Fensterhierarchie befindet

Ich habe gerade begonnen, Xcode 4.5 zu verwenden, und ich habe diesen Fehler in der Konsole:

Warnung: Versuch, < finishViewController: 0x1e56e0a0 > auf < ViewController: 0x1ec3e000> zu präsentieren, dessen View nicht in der Windowshierarchie ist!

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

Dies ist der Code, den ich verwende, um zwischen den Ansichten zu wechseln:

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

[self presentViewController:finished animated:NO completion:NULL];

1voto

Wes Punkte 1009

Ich hatte dieses Problem, und die Ursache war das Abonnieren einer Schaltfläche klicken Handler (TouchUpInside) mehrere Male.

Es wurde in ViewWillAppear abonniert, das mehrfach aufgerufen wurde, da wir die Navigation hinzugefügt hatten, um zu einem anderen Controller zu gehen und dann wieder zu diesem zurückzuspulen.

1voto

Fan Jin Punkte 2294

Leider hat die akzeptierte Lösung in meinem Fall nicht funktioniert. Ich habe versucht, zu einem neuen View Controller zu navigieren, nachdem ich von einem anderen View Controller abgewickelt wurde.

Ich habe eine Lösung gefunden, indem ich ein Flag verwendet habe, das angibt, welche Abspulsequenz aufgerufen wurde.

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

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

Dann präsentieren Sie den gesuchten 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 lässt mich der obige Code die Rückabwicklung von login/SignUp VC abfangen und zum Dashboard navigieren, oder die Rückabwicklungsaktion von Passwort vergessen VC abfangen und zur Login-Seite navigieren.

1voto

Cœur Punkte 34332

In Ihrem Hauptfenster wird es wahrscheinlich immer wieder Zeiten mit Übergängen geben, die mit der Darstellung eines Alarms unvereinbar sind. Um die Anzeige von Warnmeldungen zu jedem Zeitpunkt im Lebenszyklus Ihrer Anwendung zu ermöglichen, sollten Sie ein separates Fenster haben, das diese Aufgabe übernimmt.

/// 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 vornherein zum Erfolg führt:

[AlertWindow presentAlertWithTitle:@"My title" message:@"My message"];

1voto

Devbot10 Punkte 1203

Mit Swift 3...

Eine andere mögliche Ursache, die mir passiert ist, war eine Überleitung von einer tableViewCell zu einem anderen ViewController auf dem Storyboard. Ich verwendete auch override func prepare(for segue: UIStoryboardSegue, sender: Any?) {} wenn die Zelle angeklickt wurde.

Ich habe dieses Problem behoben, indem ich eine Überleitung von ViewController zu ViewController erstellt habe.

1voto

vonox7 Punkte 944

Es ist mir passiert, dass die Überleitung im Storyboard war eine Art kaputter . Durch Löschen der Überleitung (und erneutes Erstellen der gleichen Überleitung) wurde das Problem gelöst.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X