开发者

viewDidAppear called twice on the same instance, but only the first time this class loads form NIB

开发者 https://www.devze.com 2023-01-06 13:47 出处:网络
I have a navigation controller. One of the views adds custom subviews in its viewDidAppear:. I notice that the first time I navigate to an instance of this view controller after launching the app, vie

I have a navigation controller. One of the views adds custom subviews in its viewDidAppear:. I notice that the first time I navigate to an instance of this view controller after launching the app, viewDidAppear: invokes twice. If I pop this view off the stack and开发者_StackOverflow navigate to it again, viewDidAppear: invokes only once per appearance. All subsequent appearances invoke viewDidAppear: once.

The problem for me is that the first time I get to this view I end up with twice the number of subviews. I work around this problem by introducing a flag variable or some such, but I'd like to understand what is happening and how come I get two invocations in these circumstances.


You should never rely on -viewWillAppear:/-viewDidAppear: being called appropriately balanced with the disappear variants. While the system view controllers will do the best they can to always bracket the calls properly, I don't know if they ever guarantee it, and certainly when using custom view controllers you can find situations where these can be called multiple times.

In short, your -viewWillAppear:/-viewDidAppear: methods should be idempotent, meaning if -viewDidAppear: is called twice in a row on your controller, it should behave properly. If you want to load custom views, you may want to do that in -viewDidLoad instead and then simply put the on-screen (if they aren't already) in -viewDidAppear:.

You could also put a breakpoint in your -viewDidAppear: method to see why it's being called twice the first time it shows up.


maybe you invoke viewDidAppear in viewDidLoad (or some other stuff is going on there), since it's invoked only once during loading the view from the memory. It would match, that it's invoked two times only the first time.


This was not an iOS 5 bug, but a hidden behavior of addChildViewController:. I should file a radar for lack of documentation, I think https://github.com/defagos/CoconutKit/issues/4


If you have a line like this in your AppDelegate

window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

make sure you DON'T have a "Main nib file base name" property in your plist set to "Window.xib" or whatever your custom window nib is named. If you do, remove that row from your plist and make sure you something like

yourRootVC = [[UIViewController alloc] init];
[window setRootViewController:yourRootVC];

in your AppDelegate after instantiating your window. In most cases, you could then safely delete the Window.xib as well.


You definitely should provide more info.

Is this the root view controller?
Maybe you initiate the navigation controller with this root view controller and then push it to the navigation controller once again?


Another solution that may have been your underlying cause: Be sure you are not presenting any new view controllers from within your viewWillAppear: method.

I was calling:

[appDel.window.rootViewController presentViewController:login animated:YES completion:nil];

from within viewWillAppear and seeing my originating VC's viewDidAppear: method called twice successively with the same stack trace as you mention. And no intermediary call to viewDidDisappear:

Moving presentViewController: to the originating VC's viewDidAppear: method cleared up the double-call issue, and so now the flow is:

  1. Original viewDidAppear: called
    • Call presentViewController here
  2. Original viewDidDisappear: called
  3. New view is presented and no longer gives me a warning about "unbalanced VC display"

Fixed with help from this answer: https://stackoverflow.com/a/13315360/1143123 while trying to resolve "Unbalanced calls to begin/end appearance transitions for ..."


it's such an annoying problem, you'd think it runs once but then I now found out about this which is causing mayhem... This applies to all 3 (ViewDidAppear, ViewDidLoad, and ViewWillAppear), I am getting this when integrating with a payment terminal; once it finish calling the API, the window is being re-loaded when it's already on-screen and all it's memory is still there (not retained).

I resolved it by doing the following to all the routines mentioned above, below is a sample to one of them:

BOOL viewDidLoadProcessed = false;

-(void)viewDidLoad:(BOOL)animated
{
    if (!viewDidLoadProcessed)
    {
        viewDidLoadProcessed = YES;
        .
        .
        .
        ... do stuff here... 
        .
        .
    }
}

Repeat the above for all the other two, this prevents it from running twice. This never occurred before Steve Jobs died !!!

Kind Regards Heider Sati


Adding [super viewDidAppear:animated]; worked for me:

//Called twice
- (void)viewDidAppear:(BOOL)animated{

}

//Called once
- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号