ios 推送多个细节视图控制器时,“对 DetailViewController 开始/结束外观转换的不平衡调用”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9088465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Unbalanced calls to begin/end appearance transitions for DetailViewController" when pushing more than one detail view controller
提问by Gruntcakes
I have a view controller that contains a table view, the items in the table can be selected and a detail view controller duly created.
我有一个包含表视图的视图控制器,可以选择表中的项目并正确创建详细视图控制器。
The items in the table represent items that can have a time based trigger associated with them and a local notification is scheduled for each item, if the app is in the foreground when a local notification expires then the detail view for the item is automatically displayed.
表中的项目代表可以具有与其关联的基于时间的触发器的项目,并且为每个项目安排本地通知,如果本地通知到期时应用程序在前台,则项目的详细视图将自动显示。
I have a problem that manifests when two notifications expire at the same time which results in the views not being displayed properly and in addition the console logs: "Unbalanced calls to begin/end appearance transitions for NNN" where NNN is my detail view controller.
我有一个问题,当两个通知同时到期时,会导致视图无法正确显示,此外控制台记录:“NNN 开始/结束外观转换的不平衡调用”,其中 NNN 是我的详细信息视图控制器。
The table view controller is created as follows:
表视图控制器创建如下:
self.tableViewController = [[TableViewController alloc] initWithNibName:@"TableView" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.tableViewController];
self.window.rootViewController = navController;
When a local notification expires and didReceiveLocalNotification: is invoked the app broadcasts a notification using NSNotifcationCenter postNotificationName: and to which the table view controller is listening for. When the table view controller receives that notification it creates the detail view controller and pushes it to the stack as:
当本地通知过期并调用 didReceiveLocalNotification: 时,应用程序会使用 NSNotifcationCenter postNotificationName: 广播通知,并且表视图控制器正在侦听该通知。当表视图控制器收到该通知时,它会创建详细视图控制器并将其推送到堆栈中,如下所示:
[self.navigationController pushViewController:detailViewController animated:YES];
I read somewhere that there could be a problem if a view controller pushes another view controller when it itself is not on the top of the stack - so I thought this must be the problem, because when the table view controller receives the 2nd notification it will no longer be on the top of the navigation stack because it will have previously just pushed a detail view controller onto the stack when the first notification arrived.
我在某处读到如果视图控制器在它本身不在堆栈顶部时推送另一个视图控制器可能会出现问题 - 所以我认为这一定是问题,因为当表视图控制器收到第二个通知时不再位于导航堆栈的顶部,因为它之前只是在第一个通知到达时将详细视图控制器推送到堆栈上。
So I changed the push code to this:
所以我把推送代码改成这样:
[[self.navigationController topViewController].navigationController pushViewController:detailController animated:YES];
But it made no difference.
但这并没有什么区别。
So I next thought there could be a problem because the first detail view controller was not getting the chance to fully display before the 2nd view controller was pushed - so I changed my app's notification posting from using:
所以我接下来认为可能有问题,因为第一个细节视图控制器在第二个视图控制器被推送之前没有机会完全显示 - 所以我改变了我的应用程序的通知发布使用:
[[NSNotificationCenter defaultCenter] postNotificationName:
to
到
[[NSNotificationQueue defaultQueue] enqueueNotification: postingStyle:NSPostWhenIdle]
So that the pushes wouldn't occur within the same iteraction of the app loop. But that made no difference, nor did attempting to introduce a delay to the pushing of the detail view controlle:
这样推送就不会发生在应用程序循环的同一次迭代中。但这并没有什么不同,也没有试图延迟细节视图控件的推送:
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[[self.navigationController topViewController].navigationController pushViewController:detailController animated:YES];
});
I've no idea what the problem is or what to try next, any ideas?
我不知道问题是什么或接下来要尝试什么,有什么想法吗?
回答by railwayparade
"The unbalanced calls to begin/end appearance transitions"
“开始/结束外观过渡的不平衡调用”
occurs when you try and display a new viewcontroller before the current view controller is finished displaying. You can reproduce it by navigating in viewWillAppear.
在当前视图控制器完成显示之前尝试显示新的视图控制器时发生。您可以通过在 viewWillAppear 中导航来重现它。
Basically you are trying to push two view controllers onto the stack at almost the same time. Suggest you maintain a queue in the tableview controller which maintains a list of the detail views which need displaying. Push one at a time on to the stack and check on exit from the current detail view whether there are any queued detail views which need displaying.
基本上,您试图几乎同时将两个视图控制器推送到堆栈上。建议您在 tableview 控制器中维护一个队列,该队列维护需要显示的详细视图列表。一次将一个推入堆栈,并在退出当前详细视图时检查是否有任何需要显示的排队详细视图。
This kind of navigation is going to be confusing for the user. It may be better to consider making your detail view support multiple items.
这种导航会让用户感到困惑。最好考虑让您的详细信息视图支持多个项目。
回答by infiniteLoop
'Unbalanced calls to begin/end appearance transitions for '
'开始/结束外观过渡的不平衡调用'
Says an animation is started before the last related animation isnt done. So, are you popping any view controller before pushing the new one ? Or may be popping to root ? if yes try doing so without animation. i.e,
说动画在最后一个相关动画未完成之前开始。那么,在推送新的视图控制器之前,您是否弹出任何视图控制器?或者可能会弹出到 root ?如果是,请尝试在没有动画的情况下这样做。IE,
[self.navigationController popToRootViewControllerAnimated:NO];
And see if this resolves the issue, In my case this did the trick.
看看这是否解决了问题,在我的情况下,这解决了问题。
回答by Gabriel
"The unbalanced calls to begin/end appearance transitions" error occurs when you try and display a new viewcontroller before the current view controller is finished displaying.
当您在当前视图控制器完成显示之前尝试显示新的视图控制器时,会发生“对开始/结束外观转换的不平衡调用”错误。
So, you have to be sure you wont present a new VC until the first finishes its animations.
因此,您必须确保在第一个完成动画之前不会展示新的 VC。
Use didShowViewController and willShowViewController to block presenting a new VC before the old one completes its animation. It's for backButtonAction who makes a popViewController with Animation: YES.
使用 didShowViewController 和 willShowViewController 阻止在旧的 VC 完成动画之前呈现新的 VC。它是为 backButtonAction 制作带有动画的 popViewController 的:YES。
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self.myNavView.backButton addTarget:self action:@selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside];
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self.myNavView.backButton removeTarget:self action:@selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside];
}
回答by infinite-loop
It can also happen when you try to pop a VC from the stack more than once. On my case, the method that popped the VC was mistakenly being called multiple times. Once I cleaned that up the issue went away.
当您尝试多次从堆栈中弹出 VC 时,也会发生这种情况。就我而言,弹出 VC 的方法被错误地多次调用。一旦我清理了它,问题就消失了。
回答by Nicolas Miari
In my case, I was implementing a custom container view controller, and I was getting the warning when swapping child view controllers, despite the fact that I was calling bothbeginAppearanceTransition(_:animated:)
andendAppearanceTransition()
on both the entering and the exiting view controllers.
就我而言,我正在实施一项自定义容器视图控制器,并交换子视图控制器的时候,我得到了警告尽管我打电话都beginAppearanceTransition(_:animated:)
和endAppearanceTransition()
在进入和退出的视图控制器两者。
I solved it by reordering the method callsfor the enteringview controller; from:
我通过重新排序进入视图控制器的方法调用来解决它;从:
addChildViewController(newContent)
targetContainer.insertSubview(newContent.view, at: 0)
newContent.beginAppearanceTransition(true, animated: animated)
// Called AFTER adding subview
to:
到:
// Called BEFORE adding subview
newContent.beginAppearanceTransition(true, animated: animated)
addChildViewController(newContent)
targetContainer.insertSubview(newContent.view, at: 0)
Hope this helps someone!
希望这可以帮助某人!
回答by ymutlu
Actually you need to wait till the push animation ends. So you can delegate UINavigationController and prevent pushing till the animation ends.
实际上你需要等到推送动画结束。所以你可以委托 UINavigationController 并防止推送直到动画结束。
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
waitNavigation = NO;
}
-(void)showGScreen:(id)gvc{
if (!waitNavigation) {
waitNavigation = YES;
[_nav popToRootViewControllerAnimated:NO];
[_nav pushViewController:gvc animated:YES];
}
}
回答by lakum vishal
as mentioned in above answers this error accuses when we try to push a view controller before the previous view controller is finish loading, so one solution is that try to push controller after it finish loading, i.e. move your push view controller code from viewWillAppear to viewDidAppear
正如上面的回答中提到的,当我们在前一个视图控制器完成加载之前尝试推送视图控制器时,这个错误会指责这个错误,所以一个解决方案是在完成加载后尝试推送控制器,即将你的推送视图控制器代码从 viewWillAppear 移动到 viewDidAppear
this solution worked in my case :)
这个解决方案在我的情况下有效:)
回答by berbie
In my case the problem is that I am presenting a viewController (alert) on an already presented viewController (full screen sheet).
UIKit walks up the viewController parent chain but not the presenting chain so there is a mismatch when reaching the presented and the window root view controller.
Manually calling beginAppearanceTransition
in these cases made the message go away, though is seems rather a patch for a symptom than a real remedy for the error.
就我而言,问题是我在已经呈现的 viewController(全屏表单)上呈现了一个 viewController(警报)。UIKit 沿着 viewController 父链而不是呈现链向上走,因此在到达呈现和窗口根视图控制器时存在不匹配。beginAppearanceTransition
在这些情况下手动调用会使消息消失,尽管这似乎是针对症状的补丁,而不是对错误的真正补救措施。
回答by Tim
You can add a breakpoint to
您可以添加断点到
-[UIViewController _endAppearanceTransition:]
from where UIKitprints
从那里UIKit的版画
"Unbalanced calls to begin/end appearance transitions for %@."
This can help you with your investigations
这可以帮助您进行调查
回答by Ioannis Kousis
Look at these overloads:
看看这些重载:
If they are empty, then remark them and rebuild.
如果它们是空的,那么注释它们并重建。
- (void) beginAppearanceTransition:(BOOL) isAppearing animated:(BOOL)animated {}
- (void) becomeActive:(NSNotification *) notification {}