Warning:attempt to present A on B whose view isn't in the window hierarchy!

Source: Internet
Author: User

Yesterday to write a watercress broadcast demo, in order to write the simple demo, the use of storyboard, the results of the execution view jump encountered this problem:

Warning:attempt to present <UINavigationController:0x8d514e0> on <OAuthViewController:0xa044a60> whose View isn't in the window hierarchy!

Its function is oauthviewcontroller for user authorization, after obtaining the user's authorization, will get the Access_token to save through Nsuserdefaults. Then the next time you open the program, first determine whether Access_token already exists, and if it already exists, jump directly to Uinavigationcontroller. The code is as follows:

-(void) viewdidload {[Super viewdidload];    spinner_view.hideswhenstopped = YES;    [WebView setdelegate:self]; [WebView Setscalespagetofit:yes];If the authorized user's access_token has been saved, jump directly to Uinavigationcontroller nsuserdefaults*userdefaults = [Nsuserdefaults standarduserdefaults]; Access_token = [Userdefaults objectforkey:@ "Access_token"]; if (Access_token) {[Self performseguewithidentifier:@ "Gotosay" sender:nil];Return } nsstring*paramclientid = [NSString stringWithFormat:@ "client_id=%@", Api_key]; NSString*paramredirect_uri = [NSString stringWithFormat:@ "redirect_uri=%@ ", Redirect_uri]; NSString *paramresponse_type = @ "Response_type=code *paramscope = @ "Shuo_basic_r,shuo_basic_w,douban_basic_ Common "; //in other API calls may extend the scope parameter nsstring *getauthcode = [nsstring Stringwithformat:@ "%@? %@&%@&%@&%@ *request = [nsurlrequest requestwithurl:[nsurl Urlwithstring:getauthcode]]; [Spinner_view startanimating]; [WebView loadrequest:request];}             


The problem has occurred, unable to complete the jump of the view, but the user's access_token has been successfully saved in the Preferences plist file. The error message for the console output is as shown above.

Check the information, found the problem (StackOverflow above the master really a lot of AH), first give two to me very helpful URL:

[iOS Development Exception]whose view is not in the window hierarchy!

Loadview, Viewdidload, Viewwillappear, Viewdidappear and other detailed

Workaround:

Transfer code that verifies that Access_token is already present in the Viewdidappear method:

-(void) Viewdidappear: (BOOL) Animated {    //If the Access_token of the authorized user has been saved, jump directly to Uinavigationcontroller    Nsuserdefaults *userdefaults = [Nsuserdefaults standarduserdefaults];    Access_token = [Userdefaults objectforkey:@ "Access_token"];    if (access_token) {        [self performseguewithidentifier:@ "Gotosay" sender:nil];        return;}}     


Analysis:

Programmers who believe in single-step debugging know that only the Viewdidload method is fully executed to actually load the corresponding interface in the window. There is a problem in the pre-modification program, note that this action occurs in the Viewdidload method of a:

[performseguewithidentifier:@sender:nil];  


The function is to jump from A to B.

Then after the segue call, the program calls the Viewdidload method of B, and after the Viewdidload method of B is executed, it returns to the Viewdidload method of a to execute the remaining statements. Then, when the window loads the view, its hierarchy is confusing, so the error (of course, if you jump from a to B and then there are statements, the last load is a view).

The difference between the Viewdidappear method and the Viewdidload method is that the view has not completely transitioned to the window when the Viewdidload method is called, and the view has completely transitioned to the window when the method call is Viewdidappear.

Therefore, calling the Performsegue method in the Viewdidappear method to implement the view jump will not have the above problem, because the program will be ordered to execute a Viewdidload method, after the completion of the method, Then execute the segue jump in the Viewdidappear method and execute the Viewdidload method of B, so there will be no confusion.

When I want to jump from one VC to another VC, the general will use

-(void) Presentviewcontroller: (Uiviewcontroller *) viewcontrollertopresent animated: (BOOL) flag completion: ( void (^) (void)) completion; Of course, you can also use navigation push.

But yesterday met the topic of warning, in StackOverflow found the answer: Click to open the link

The main idea is that page jumps must be done after Viewdidload and viewdidappear. The solution is to make sure that the page jumps after view load is complete. The great God said that can be achieved by setting the delay, through the experiment I think this bad control, in the end need to delay how much?

Later, a plan was changed to use the Viewdidload

[selfperformselectoronmainthread:@selector(login) withobject:Nil Waituntildone:NO];

Write the page jump code into the function, and then set the Waituntildone to No, that is, viewdidload directly returned without login execution. This makes sure that the page jumps in login are executed after viewdidload.

In addition, I also encountered the following situation: A page jumps to B, in B is also encapsulated a page jump (to C).

That is, in the previous login function, a jump from A to B will be passed tokens, secret and so on to obtain user authorization data, and then in B to adjust the large companies in the packaging of the authorization page (such as Baidu Network disk, Sina Weibo).

At first my login implementation is as follows:

-(void) login

{

Loginviewcontroller *loginvc=[[loginviewcontrolleralloc] init];

LOGINVC. delegate= self;

[self presentviewcontroller:loginvc animated:NOCompletion:nil];

[LOGINVC auth:baidu_api_key secret:nil disk:baidu];//This function has a jump to the authorization page. /c6>

}

This also causes the problem, and the solution is to put the last line of functions in the completion block.

-(void) login

{

Loginviewcontroller *loginvc=[[loginviewcontroller alloc] init];

LOGINVC. delegate= self;

[self presentviewcontroller:loginvc animated:NO completion:^{[loginvc auth:BAIDU _api_key Secret:nil disk:BAIDU];}];

}

Because:

The completion handler, if provided, 'll be a invoked after the presented controllers Viewdidappear:callback is invoked.

Warning:attempt to present A on B whose view isn't in the window hierarchy!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.