对 < UITabBarController: 0x197870 > 的开始/结束外观转换的不平衡调用

我读到另一个用户遇到类似的 错误,但这个错误是在不同的情况下。

当我最初添加一个视图控制器时,我收到了这个消息:

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视图控制器之后,将显示上面的错误。

另外,我正在使用 xCode 4.2和 iOS 5.0 SDK 开发 iOS 4.3应用程序。

126129 次浏览

没有看到更多的周围的代码,我不能给出一个明确的答案,但我有两个理论。

  1. 您没有使用 UIViewController指定初始化程序 initWithNibName:bundle:。请尝试使用它而不仅仅是 init

  2. 此外,self可能是选项卡条控制器的视图控制器之一。始终显示来自最顶层视图控制器的视图控制器,这意味着在这种情况下要求选项卡条控制器代表视图控制器显示覆盖视图控制器。您仍然可以保留对实际视图控制器的任何回调委托,但是必须让选项卡栏控制器出现并解除。

我在同一个问题上遇到了很多问题,我解决了这个问题

  1. 使用 Storyboad instantiateViewControllerWithIdentifier 方法(即 Intro *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"introVC"];)初始化 ViewController
  2. [self.tabBarController presentModalViewController : vc animated:YES];

我有在我的故事板的视图控制器,由于某些原因,只使用 [[introvc alloc] init];不适合我。

我通过将动画从 YES 改为 NO 来修正这个错误。

来自:

[tabBarController presentModalViewController:viewController animated:YES];

致:

[tabBarController presentModalViewController:viewController animated:NO];

当我需要从另一个视图控制器显示我的登录视图控制器时,我也遇到了同样的问题。如果用户没有被授权,我会在另一个视图控制器的 ViewDidLoad 方法中进行显示(如果没有被授权-> presModalViewController)。当我开始在 ViewDidAppear 方法中创建它时,我解决了这个问题。我认为 ViewDidLoad 只是初始化属性,然后实际的显示视图算法就开始了!这就是为什么您必须使用 viewDidAppear 方法来进行模态转换!

当我从根 TVC 导航到 TVC A,然后再到 TVC B 时,我遇到了这个问题。点击 TVC B 中的“加载”按钮后,我想直接跳回到根 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];

当我将一个 UIButton 连接到一个故事板接续动作(在 IB 中)时,我遇到了这个错误,但后来决定让这个按钮通过编程方式调用 performSegueWithIdentifier,忘记从 IB 中删除第一个按钮。

实际上,它执行了两次 segue 调用,出现了这个错误,实际上推动了我的视图两次。修复方法是删除一个 segue 调用。

希望这能帮到像我这么累的人!

我也遇到了同样的问题,我在第一个 UIViewController中调用了 viewDidLoad内部的一个方法

- (void)viewDidLoad{
[super viewDidLoad];


[self performSelector:@selector(loadingView)
withObject:nil afterDelay:0.5];
}


- (void)loadingView{


[self performSegueWithIdentifier:@"loadedData" sender:self];
}

在第二个 UIViewController中,我也做了同样的事情,只是延迟了0.5秒。在将延迟改为更高的值后,它工作得很好。就好像一个接一个的接续不能进行得太快。

我通过写作解决了这个问题

[self.navigationController presentViewController:viewController
animated:TRUE
completion:NULL];

我也犯了同样的错误。我有一个标签栏3个项目,我是无意识地尝试调用根视图控制器的项目1在项目2我的标签栏使用 performSegueWithIdentifier

发生的情况是,它调用视图控制器,并在几秒钟后返回项2的根视图控制器,并记录该错误。

显然,您不能将一个项的根视图控制器调用到另一个项。

所以不是 performSegueWithIdentifier

我用的是 [self.parentViewController.tabBarController setSelectedIndex: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];
}
}

我也有同样的问题,所以我想我应该发布一下,以防其他人也遇到类似的情况。

在我的例子中,我在我的 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];


}

在我的例子中,我收到了错误消息,因为长按识别器触发了不止一次,结果,我的“ SomViewController”被多次推送到堆栈上。

解决方案是添加一个布尔值,以指示 SomViewController 何时被推送到堆栈上。当调用 UITableViewController 的 viewWillAppear 方法时,我将布尔值设置回 NO。

Danh发布

您可以通过在应用程序完成初始化之前显示模态 vc 来生成此警告。例如,启动一个选项卡式的应用程序模板应用程序,在 self. tabBarController 顶部显示一个模态 vc 作为应用程序的最后一行: did FinishLaunching。警告出现。解决方案: 让堆栈首先展开,在另一个方法中显示模态 vc,使用 PerformSelector withTD: 0.0进行调用

尝试将该方法移动到 viewWillAppear 并保护它,以便它只执行一次(建议设置一个属性)

正如@danh 所建议的,我的问题是我在 UITabBarController准备好之前就展示了模态 vc。然而,在展示视图控制器之前依赖一个固定的延迟让我感到不舒服(根据我的测试,我需要在 performSelector:withDelay:中使用0.05 -0.1 s 的延迟)。我的解决方案是添加一个在 UITabBarControllerviewDidAppear:方法上调用的块:

PRTabBarControler.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;
};

我遇到了第三方代码的问题。有人忘记在自定义 TabBarController 类中设置 viewWillAppear 和 viewWillDisaper 的超级内部。

- (void) viewWillAppear:(BOOL)animated {


[super viewWillAppear:animated];
// code...
}


or


- (void) viewWillDisappear:(BOOL)animated {


[super viewWillDisappear:animated];
// code...
}

我有这个问题是因为一个打印错误:

override func viewDidAppear(animated: Bool) {
super.viewWillAppear(animated)

而不是

override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)

它在管理员那里叫“ WillAppear”而不是“ DidAppear”

对于许多情况,另一个解决方案是确保 UIViewController之间的转换发生 之后不合适的(如初始化期间)过程完成,方法是:

__weak MyViewController *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf presentViewController:vc animated:YES];
});

这对于 pushViewController:animated:等也是通用的。

我发现,如果您正在使用情节串连图板,您将希望将呈现新视图控制器的代码放在 viewDidAppear 中。它还将消除“不鼓励在分离的视图控制器上显示视图控制器”的警告。

对我来说,在 Swift 2 + 工作:

我在情节串连图板中有 UITabBarViewController,我选择了像下面这样的 Index 属性:

enter image description here

但我删除了它,并添加了初始类的 viewDidLoad 方法,如下所示:

override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.selectedIndex = 2
}

我希望我能帮助别人。

如果您正在使用 transitioningDelegate(在本问题的示例中不是这种情况) ,也将 modalPresentationStyle设置为 .Custom

斯威夫特

let vc = storyboard.instantiateViewControllerWithIdentifier("...")
vc.transitioningDelegate = self
vc.modalPresentationStyle = .Custom

你需要确保-(void) stargialance 传递: (BOOL) is 传递动画: (BOOL)传递动画和-(void) end 传递动画是在类中一起创建的。

我也有同样的问题。在开发时,我想绕过屏幕。我通过调用选择器方法在 viewDidLoad 中从一个视图控制器导航到另一个视图控制器。

问题是我们应该让 ViewController 在转换到另一个 ViewController 之前完成转换。

这解决了我的问题: 延迟是必要的,允许 ViewController 在转换到另一个之前完成转换。

self.perform(#selector(YOUR SELECTOR METHOD), with: self, afterDelay: 0.5)


Swift 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


}

对我来说,发生这个错误是因为在设置 root 视图控制器时,我没有在类的上层声明 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,那么我将收到错误

当尝试呈现通过闭包延迟初始化的 UINavigationController时,将显示此错误。