我读到了关于遇到类似error的其他用户的SO,但此错误的情况不同。
我最初添加View Controller时收到此消息:
Unbalanced calls to begin/end appearance transitions for
<UITabBarController: 0x197870>
应用程序的结构如下:
我有一个5个标签的TabBarController链接到5个视图控制器。在初始显示标签中,我调出一个新的视图控制器作为应用程序的介绍进行叠加。
我使用此代码调用简介视图控制器:
IntroVC *vc = [[IntroVC alloc] init];
[self presentModalViewController:vc animated:YES];
[vc release];
显示此IntroVC
视图控制器后,显示上述错误。
P.S。我正在使用xCode 4.2&amp; iOS 5.0 SDK,开发iOS 4.3应用程序。
答案 0 :(得分:93)
如果没有看到更多的周围代码,我无法给出明确的答案,但我有两个理论。
您没有使用UIViewController
的{{3}}。尝试使用它而不仅仅是init
。
此外,self
可能是标签栏控制器的视图控制器之一。始终从最顶层的视图控制器提供视图控制器,这意味着在这种情况下要求标签栏控制器代表视图控制器显示重叠视图控制器。您仍然可以将任何回调代理保留在实际视图控制器中,但您必须将标签栏控制器存在并解除。
答案 1 :(得分:38)
我通过将动画从YES更改为NO来修复此错误。
自:
[tabBarController presentModalViewController:viewController animated:YES];
要:
[tabBarController presentModalViewController:viewController animated:NO];
答案 2 :(得分:15)
由danh
发布您可以通过在应用程序初始化之前显示模态vc来生成此警告。即启动一个选项卡式应用程序模板应用程序,并在self.tabBarController之上呈现一个模态vc作为application:didFinishLaunching中的最后一行。出现警告。解决方案:让堆栈首先展开,在另一个方法中显示模态vc,使用performSelector withDelay调用:0.0
尝试将方法移动到viewWillAppear并保护它,以便它只执行一次(建议设置属性)
答案 3 :(得分:4)
许多情况下的另一个解决方案是确保UIViewController
之间的转换在不适合(如初始化期间)过程完成后发生,执行以下操作:
__weak MyViewController *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf presentViewController:vc animated:YES];
});
这也适用于pushViewController:animated:
等。
答案 4 :(得分:3)
当我需要从另一个视图控制器呈现我的登录视图控制器时,我遇到了同样的问题如果用户未被授权,我在我的另一个视图控制器的ViewDidLoad方法中做了(如果没有授权 - > gt; presentModalViewController) 。当我开始在ViewDidAppear方法中创建它时,我解决了这个问题。我认为ViewDidLoad只初始化属性,然后实际显示视图算法开始!这就是为什么你必须使用viewDidAppear方法进行模态转换!
答案 5 :(得分:3)
我遇到了同样的问题。我在第一个viewDidLoad
UIViewController
内的方法
- (void)viewDidLoad{
[super viewDidLoad];
[self performSelector:@selector(loadingView)
withObject:nil afterDelay:0.5];
}
- (void)loadingView{
[self performSegueWithIdentifier:@"loadedData" sender:self];
}
在第二个UIViewController
内,我也做了同样的延迟0.5秒。将延迟更改为更高的值后,它工作正常。这就像segue在另一个segue之后执行得太快了。
答案 6 :(得分:2)
我在同一个问题上遇到了很多问题。
我解决了这个问题Intro *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"introVC"];
[self.tabBarController presentModalViewController : vc animated:YES];
我的故事板中有viewcontroller,因为某些原因只使用[[introvc alloc] init];
对我不起作用。
答案 7 :(得分:2)
如果您使用的是transitioningDelegate
(不是此问题示例中的情况),请将 modalPresentationStyle
设置为 .Custom
夫特
let vc = storyboard.instantiateViewControllerWithIdentifier("...")
vc.transitioningDelegate = self
vc.modalPresentationStyle = .Custom
答案 8 :(得分:2)
由于输入错误我遇到了这个问题:
override func viewDidAppear(animated: Bool) {
super.viewWillAppear(animated)
而不是
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
在超级中称为“WillAppear”而不是“DidAppear”
答案 9 :(得分:2)
我通过写
解决了这个问题[self.navigationController presentViewController:viewController
animated:TRUE
completion:NULL];
答案 10 :(得分:1)
我遇到了同样的问题,并且认为如果其他人遇到类似的事情我会张贴。
就我而言,我已将长按手势识别器附加到我的UITableViewController。
UILongPressGestureRecognizer *longPressGesture = [[[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:@selector(onLongPress:)]
autorelease];
[longPressGesture setMinimumPressDuration:1];
[self.tableView addGestureRecognizer:longPressGesture];
在我的onLongPress选择器中,我启动了我的下一个视图控制器。
- (IBAction)onLongPress:(id)sender {
SomeViewController* page = [[SomeViewController alloc] initWithNibName:@"SomeViewController" bundle:nil];
[self.navigationController pushViewController:page animated:YES];
[page release];
}
在我的情况下,我收到了错误消息,因为长按识别器触发了多次,因此,我的&#34; SomeViewController&#34;被多次推入堆栈。
解决方案是添加一个布尔值来指示SomeViewController何时被推入堆栈。当调用我的UITableViewController的viewWillAppear方法时,我将布尔值设置回NO。
答案 11 :(得分:1)
我有同样的错误。我有一个包含3个项目的标签栏,我无意识地尝试使用performSegueWithIdentifier
在我的标签栏的项目2中调用项目1的根视图控制器。
它会调用视图控制器并在几秒钟后返回到第2项的根视图控制器并记录该错误。
显然,您无法将项目的根视图控制器调用到另一个项目。
而不是performSegueWithIdentifier
我使用了[self.parentViewController.tabBarController setSelectedIndex:0];
希望这有助于某人。
答案 12 :(得分:1)
我遇到了第三方代码的问题。有人忘了在自定义TabBarController类中设置viewWillAppear和viewWillDisappear中的super。
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// code...
}
or
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// code...
}
答案 13 :(得分:1)
Swift 2 + 对我来说有效:
我在故事板中有UITabBarViewController,我有这样的selectedIndex属性:
但我删除它,并添加我的初始类的viewDidLoad方法,如下所示:
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.selectedIndex = 2
}
我希望我能帮助别人。
答案 14 :(得分:0)
实际上你需要等到推动画结束。因此,您可以委派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];
}
}
答案 15 :(得分:0)
正如@danh建议的那样,我的问题是我在UITabBarController
准备好之前呈现了模态vc。但是,在呈现视图控制器之前我依赖固定的延迟感到不舒服(从我的测试中,我需要在performSelector:withDelay:
中使用0.05-0.1s延迟)。我的解决方案是添加一个在UITabBarController
viewDidAppear:
方法上调用的块:
PRTabBarController.h:
@interface PRTabBarController : UITabBarController
@property (nonatomic, copy) void (^viewDidAppearBlock)(BOOL animated);
@end
PRTabBarController.m:
#import "PRTabBarController.h"
@implementation PRTabBarController
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.viewDidAppearBlock) {
self.viewDidAppearBlock(animated);
}
}
@end
现在在application:didFinishLaunchingWithOptions:
PRTabBarController *tabBarController = [[PRTabBarController alloc] init];
// UIWindow initialization, etc.
__weak typeof(tabBarController) weakTabBarController = tabBarController;
tabBarController.viewDidAppearBlock = ^(BOOL animated) {
MyViewController *viewController = [MyViewController new];
viewController.modalPresentationStyle = UIModalPresentationOverFullScreen;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[weakTabBarController.tabBarController presentViewController:navigationController animated:NO completion:nil];
weakTabBarController.viewDidAppearBlock = nil;
};
答案 16 :(得分:0)
我发现,如果您使用的是故事板,则需要在viewDidAppear中放置呈现新视图控制器的代码。它也将摆脱&#34;不鼓励在分离的视图控制器上呈现视图控制器&#34;警告。
答案 17 :(得分:0)
你需要确保 - (void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated and - (void)endAppearanceTransition在类中一起创建。
答案 18 :(得分:0)
我有同样的问题。开发时,我想绕开屏幕。我通过调用选择器方法在viewDidLoad中从一个视图控制器导航到另一个。
问题在于,我们应该让ViewController在过渡到另一个ViewController之前完成过渡。
这解决了我的问题:延迟是必要的,以便允许ViewController在过渡到另一个之前完成过渡。
self.perform(#selector(YOUR SELECTOR METHOD), with: self, afterDelay: 0.5)
答案 19 :(得分:0)
快捷键5
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//Delete or comment the below lines on your SceneDelegate.
// guard let windowScene = (scene as? UIWindowScene) else { return }
// window?.windowScene = windowScene
// window?.makeKeyAndVisible()
let viewController = ListVC()
let navViewController = UINavigationController(rootViewController: viewController)
window?.rootViewController = navViewController
}
答案 20 :(得分:0)
对我来说这个错误发生是因为我在设置根视图控制器时没有在我的类的上层声明 UIWindow
rootViewController?.showTimeoutAlert = showTimeOut
let navigationController = SwipeNavigationController(rootViewController: rootViewController!)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
例如,如果我尝试在该代码块中声明 window
而不是引用 self 那么我会收到错误
答案 21 :(得分:-1)
当我将UIButton连接到故事板segue动作(在IB中)时遇到此错误,但后来决定让按钮以编程方式调用performSegueWithIdentifier
忘记从IB中删除第一个。
本质上它执行了两次segue调用,给出了这个错误并实际上将我的视图推了两次。解决方法是删除其中一个segue调用。
希望这能帮助像我这样累的人!
答案 22 :(得分:-1)
当我从根TVC导航到TVC A然后导航到TVC B时,我遇到了这个问题。点击TVC中的“加载”按钮之后,BI想直接跳回到根TVC(无需重新访问TVC A,为什么?做它)。我有:
//Pop child from the nav controller
[self.navigationController popViewControllerAnimated:YES];
//Pop self to return to root
[self.navigationController popViewControllerAnimated:YES];
...它给出了错误“不平衡的调用开始/结束等”。以下修复了错误,但没有动画:
//Pop child from the nav controller
[self.navigationController popViewControllerAnimated:NO];
//Then pop self to return to root
[self.navigationController popViewControllerAnimated:NO];
这是我的最终解决方案,没有错误,仍然是动画:
//Pop child from the nav controller
[self.navigationController popViewControllerAnimated:NO];
//Then pop self to return to root, only works if first pop above is *not* animated
[self.navigationController popViewControllerAnimated:YES];