我有一个导航控制器。其中一个视图会在其viewDidAppear:
中添加自定义子视图。我注意到在启动应用程序后第一次导航到此视图控制器的实例时,viewDidAppear:
会调用两次。如果我将此视图从堆栈中弹出并再次导航到它,viewDidAppear:
每个外观只调用一次。所有后续出现都会调用viewDidAppear:
一次。
对我来说,问题是我第一次看到这个视图时,我最终会得到两倍的子视图。我通过引入一个标志变量或其他一些来解决这个问题,但是我想了解发生了什么,以及在这种情况下我怎么得到两次调用。
答案 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:
方法会清除双重调用问题,现在流程为:
viewDidAppear:
被召唤
presentViewController
viewDidDisappear:
名为"unbalanced VC display"
在尝试解析"Unbalanced calls to begin/end appearance transitions for ..."
答案 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