thegalah
thegalah

Reputation: 528

Changing views keeps giving me attempt to present vc1 on vc whose view is not in the window hierarchy

I've created a test application to understand how views/viewcontrollers work and how to navigate between them programmatically without a storyboard or a nib.

I've basically set up a rootViewController called Viewcontroller which is set in the AppDelegate.

This view presents view1 on startup which contains a uibutton which calls the notification in the rootViewController to present view2. However when I do this I keep getting the warning:

Warning: Attempt to present <View1: 0x7be66c80> on <ViewController: 0x7be62980> whose view is not in the window hierarchy!

My code for the controlling viewcontroller is as follows:


    #import "ViewController.h"
    #import "View1.h"
    #import "View2.h"
    @interface ViewController ()

    @end

    @implementation ViewController
    -(void) loadView{
        [super loadView];
    }
    -(void)viewDidAppear:(BOOL)animated{
        NSLog(@"View appeared");
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"view1" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(view1:) name:@"view1" object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"view2" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(view2:) name:@"view2" object:nil];
        [self showView1];
    }
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    -(void)view1:(NSNotification*) notification{
        NSLog(@"Showing view1");
        [self dismissViewControllerAnimated:YES completion:nil];
        [self showView1];
    }
    -(void)showView1{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.view.window.rootViewController presentViewController:[[View1 alloc]init] animated:YES completion:nil];
        });
    }
    -(void)view2:(NSNotification*) notification{
        NSLog(@"Showing view2");
        [self dismissViewControllerAnimated:YES completion:nil];
        [self showView2];
    }
    -(void)showView2{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self presentViewController:[[View1 alloc]init] animated:YES completion:nil];
        });
    }

@end

Edit:I forgot to mention that view1 displays initially without any errors or problems.

Edit: the code for view1 and view2 are exactly identical except that they send different notifications:


    #import "View1.h"

    @interface View1 ()

    @end

    @implementation View1

    - (void)loadView {
        [super loadView];
        self.view.frame = [[UIApplication sharedApplication].keyWindow bounds];
        // Do view setup here.
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button addTarget:self
                   action:@selector(touchedLogin:)
         forControlEvents:UIControlEventTouchUpInside];
        [button setTitle:@"Login" forState:UIControlStateNormal];

        button.layer.cornerRadius=1;
        button.frame = CGRectMake(self.view.bounds.size.width/2-100, self.view.bounds.size.height-200, 200, 60.0);
        [button setTitleEdgeInsets:UIEdgeInsetsMake(5.0, 0.0, 0.0, 0.0)];

        //[_window setBackgroundColor:[UIColor whiteColor]];
        [self.view addSubview:button];
    }
    -(void)touchedLogin:(id*)sender{
        [[NSNotificationCenter defaultCenter] postNotificationName:@"view2" object:nil];
    }

    @end

Upvotes: 0

Views: 317

Answers (1)

rdelmar
rdelmar

Reputation: 104082

You get this error because you're dismissing View1 with animation, then immediately calling showView2 (which actually shows View1, since you have [View1 alloc]init] in that method). Because the animation takes some amount of time, you're trying to present View1 while View1 is still on screen, not ViewController. In general, it's not a good idea to do dismissals and presentations, one right after the other like that. I think it might work (though I never do this) if you do the dismissal without animation.

Upvotes: 0

Related Questions