0
votes

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

1
If you get the error when you press the button in View1, then you need to show the code you have in that button's action method.rdelmar
I've added the code. Both views are the same except the other one sends the notification to show the other viewthegalah

1 Answers

0
votes

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.