iOSBeginner iOSBeginner - 5 months ago 24
iOS Question

Attempt to present View Controller Warning

I have the following ViewControllers that present the next ViewController when something is finished:

Nr1: My GameViewController checks that the game has finished and call CheckGameFinished:

-(void) checkGameFinished {
if ([self.gameModel isGameOver]) {

double delayTimeInSeconds = 3.5;
dispatch_time_t popTimeDelay = dispatch_time(DISPATCH_TIME_NOW, delayTimeInSeconds * NSEC_PER_SEC);
dispatch_after(popTimeDelay, dispatch_get_main_queue(), ^(void){

[progressBarTimer invalidate];

level2ViewController *govc = [self.storyboard instantiateViewControllerWithIdentifier:@"level2ViewController"];

[self.finishAudio play];

[self presentViewController:govc animated:NO completion:^(){
[self.gameModel clearGameData];

}];
});
}
}


Then level2ViewController appears:

- (void)viewDidLoad {
[super viewDidLoad];

double delayTimeInSeconds = 2;
dispatch_time_t popTimeDelay = dispatch_time(DISPATCH_TIME_NOW, delayTimeInSeconds * NSEC_PER_SEC);
dispatch_after(popTimeDelay, dispatch_get_main_queue(), ^(void){


GameViewController *gvc = [self.storyboard instantiateViewControllerWithIdentifier:@"gameViewController"];

[self presentViewController:gvc animated:NO completion:nil];


});

}


and called the next ViewController, and so on.

Now I get overtime the following Warnings:


Warning: Attempt to present GameViewController on level2ViewController
whose view is not in the window hierarchy!

Answer

Don't present a view controller from viewDidLoad, instead call from viewDidAppear:. Also using dispatch_after like that (assuming you are using it to hopefully make sure the view is on screen and not for gaming purposes) is a very bad practice.
When the view controller that is being loaded has done being presented (that happens when viewDidAppear: is called) you can present a different one:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    GameViewController *gvc = [self.storyboard instantiateViewControllerWithIdentifier:@"gameViewController"];
    [self presentViewController:gvc animated:NO completion:nil];
}