viewDidAppear在同一个实例上调用了两次,但只是第一次加载这个类形成NIB

时间:2010-07-07 21:42:45

标签: iphone cocoa-touch

我有一个导航控制器。其中一个视图会在其viewDidAppear:中添加自定义子视图。我注意到在启动应用程序后第一次导航到此视图控制器的实例时,viewDidAppear:会调用两次。如果我将此视图从堆栈中弹出并再次导航到它,viewDidAppear:每个外观只调用一次。所有后续出现都会调用viewDidAppear:一次。

对我来说,问题是我第一次看到这个视图时,我最终会得到两倍的子视图。我通过引入一个标志变量或其他一些来解决这个问题,但是我想了解发生了什么,以及在这种情况下我怎么得到两次调用。

8 个答案:

答案 0 :(得分:18)

你永远不应该依赖于-viewWillAppear: / -viewDidAppear:被称为与消失的变体适当平衡。虽然系统视图控制器将尽其所能,但他们总能正确地对调用进行括号,但我不知道他们是否能够保证它,当然在使用自定义视图控制器时,您可以找到可以多次调用它们的情况。

简而言之,您的-viewWillAppear: / -viewDidAppear:方法应该是幂等的,这意味着如果在控制器上连续两次调用-viewDidAppear:,它应该表现正常。如果您要加载自定义视图,可能需要在-viewDidLoad中执行此操作,然后只需将屏幕上显示(如果它们尚未存在)-viewDidAppear:

您还可以在-viewDidAppear:方法中设置一个断点,以查看它第一次出现时被调用两次的原因。

答案 1 :(得分:1)

也许你在viewDidAppear中调用viewDidLoad(或者其他一些东西在那里),因为它在从内存加载视图期间只调用一次。它会匹配,它只在第一次被调用两次。

答案 2 :(得分:1)

这不是iOS 5的错误,而是addChildViewController的隐藏行为:我想,我应该提交缺乏文件的雷达 https://github.com/defagos/CoconutKit/issues/4

答案 3 :(得分:1)

如果你的AppDelegate中有这样的一行

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

确保您没有"主nib文件基本名称"你的plist中的属性设置为" Window.xib"或者您的自定义窗口笔尖的名称。如果您这样做,请从您的plist中删除该行并确保类似

yourRootVC = [[UIViewController alloc] init];
[window setRootViewController:yourRootVC];
实例化窗口后,在AppDelegate中

。在大多数情况下,您也可以安全地删除Window.xib。

答案 4 :(得分:0)

你绝对应该提供更多信息。

这是根视图控制器吗?
也许您使用此根视图控制器启动导航控制器,然后再次将其推送到导航控制器?

答案 5 :(得分:0)

可能是您潜在原因的另一种解决方案:确保您没有在viewWillAppear:方法中展示任何新的视图控制器。

我在打电话:

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

viewWillAppear 中看到我的原始VC的viewDidAppear:方法连续两次调用相同的堆栈跟踪 。并且没有中间人致电viewDidDisappear:

presentViewController:移至原始VC的viewDidAppear:方法会清除双重调用问题,现在流程为:

  1. 原来viewDidAppear:被召唤
    • 在此致电presentViewController
  2. 原始viewDidDisappear:名为
  3. 显示了新视图,不再向我发出关于"unbalanced VC display"
  4. 的警告

    在尝试解析"Unbalanced calls to begin/end appearance transitions for ..."

    时,在此答案的帮助下修复了https://stackoverflow.com/a/13315360/1143123

答案 6 :(得分:0)

添加[super viewDidAppear:animated];为我工作:

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

}

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

答案 7 :(得分:-1)

这是一个令人烦恼的问题,你认为它运行一次,但后来我发现了这个导致混乱...这适用于所有3(ViewDidAppear,ViewDidLoad和ViewWillAppear) ,我在与支付终端集成时得到这个;一旦完成调用API,当窗口已经在屏幕上并且它的所有内存仍在那里(未保留)时,窗口将被重新加载。

我通过对上面提到的所有例程执行以下操作来解决它,下面是其中一个例子:

BOOL viewDidLoadProcessed = false;

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

对所有其他两个重复上述操作,这可以防止它运行两次。这在史蒂夫乔布斯去世之前从未发生过!

亲切的问候 Heider Sati