为啥我的 TabBar 按钮在我第一次加载视图控制器时被禁用?

Posted

技术标签:

【中文标题】为啥我的 TabBar 按钮在我第一次加载视图控制器时被禁用?【英文标题】:Why are my TabBar buttons disabled the first time I load my view controller?为什么我的 TabBar 按钮在我第一次加载视图控制器时被禁用? 【发布时间】:2011-06-14 12:31:34 【问题描述】:

我有一个 iPhone 应用程序,我可以在其中切换 2 个标签栏。问题是在我交换标签栏的视图中,我的标签栏按钮仅在第一次加载视图时被禁用(当调用 loadView 和 viewDidLoad 时)。换句话说,如果我导航到该视图,则标签栏按钮被禁用。如果我从该视图导航到某些内容然后弹回,则启用按钮。视图生命周期调用的区别在于:

工作 - 加载视图 viewDidLoad 视图将出现 viewDidAppear

不工作 - 视图将出现 viewDidAppear

现在交换位于 viewDidAppear 中。如果我将交换放在 viewWillAppear 中,按钮可以正常工作,但视图控制器会跳下来,因为标签栏交换动画是在视图转换动画期间完成的。

我的第一个猜测是某些视图位于标签栏的顶部。我不认为这是真的。我在两种情况下都打印了视图层次结构,只有一点点不同。

这是工作场景的视图层次结构:

<UIWindow: 0x5a4c7c0; frame = (0 0; 320 480); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x5a4ca30>>
   | <UILayoutContainerView: 0x5a591b0; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x5a59230>>
   |    | <UITransitionView: 0x5a59c00; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x5a59ca0>>
   |    |    | <UIViewControllerWrapperView: 0x5a6e960; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x5a6e9e0>>
   |    |    |    | <UILayoutContainerView: 0x5a5bb70; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x5a5bbc0>>
   |    |    |    |    | <UINavigationTransitionView: 0x5a5c290; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x5a19400>>
   |    |    |    |    |    | <UIViewControllerWrapperView: 0xaf01810; frame = (0 20; 320 460); layer = <CALayer: 0xaf01840>>
   |    |    |    |    |    |    | <UIView: 0x5abcba0; frame = (0 0; 320 460); layer = <CALayer: 0x5a8ff50>>
   |    |    |    |    |    |    |    | <CaptureAuxMenu: 0x5ac6850; frame = (0 480; 320 49); layer = <CALayer: 0x5ac68e0>>
   |    |    |    |    |    |    |    |    | <UIImageView: 0x5ac6a50; frame = (0 0; 320 49); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5ac6a80>>
   |    |    |    |    |    |    |    |    | <UIButton: 0x5ac67c0; frame = (18 7; 80 31); opaque = NO; layer = <CALayer: 0x5ac6b80>>
   |    |    |    |    |    |    |    |    |    | <UIImageView: 0x5acf910; frame = (0 0; 80 31); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5acf940>>
   |    |    |    |    |    |    |    |    | <UIButton: 0x5ac7ed0; frame = (116 7; 80 31); opaque = NO; layer = <CALayer: 0x5ac7b50>>
   |    |    |    |    |    |    |    |    |    | <UIImageView: 0x5acf890; frame = (0 0; 80 31); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5acf8c0>>
   |    |    |    |    |    |    |    |    | <UIButton: 0x5ac91f0; frame = (285 10; 25 25); opaque = NO; layer = <CALayer: 0x5ac8e70>>
   |    |    |    |    |    |    |    |    |    | <UIImageView: 0x5acf810; frame = (0 0; 25 25); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5acf840>>

   |    | <UITabBar: 0x5a59560; frame = (0 431; 320 480); hidden = YES; autoresize = W+TM; layer = <CALayer: 0x5a59600>>
   |    |    | <UITabBarButton: 0x5a638f0; frame = (2 1; 60 479); opaque = NO; layer = <CALayer: 0x5a660a0>>
   |    |    |    | <UITabBarSelectionIndicatorView: 0x5a6e250; frame = (0 2; 60 475); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6e280>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a662a0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a66360>>
   |    |    |    | <UITabBarButtonLabel: 0x5a63ba0; frame = (16 465; 28 13); text = 'string'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a63990>>
   |    |    | <UITabBarButton: 0x5a660d0; frame = (66 1; 60 479); opaque = NO; layer = <CALayer: 0x5a674a0>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a663c0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a66410>>
   |    |    |    | <UITabBarButtonLabel: 0x5a66cc0; frame = (16 465; 28 13); text = 'string'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a665e0>>
   |    |    | <UITabBarButton: 0x5a65990; frame = (130 1; 60 479); opaque = NO; layer = <CALayer: 0x5a68140>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a689c0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a68170>>
   |    |    |    | <UITabBarButtonLabel: 0x5a696b0; frame = (16 465; 28 13); text = 'string'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a68ba0>>
   |    |    | <UITabBarButton: 0x5a68420; frame = (194 1; 60 479); opaque = NO; layer = <CALayer: 0x5a697d0>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a6abf0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6ac40>>
   |    |    |    | <UITabBarButtonLabel: 0x5a6af20; frame = (8 465; 44 13); text = 'FRIENDS'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a678c0>>
   |    |    | <UITabBarButton: 0x5a6a5a0; frame = (258 1; 60 479); opaque = NO; layer = <CALayer: 0x5a6b230>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a6b9b0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6b260>>
   |    |    |    | <UITabBarButtonLabel: 0x5a677c0; frame = (8 465; 44 13); text = 'PROFILE'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6b3d0>>
   |    | <UIImageView: 0x5a6b850; frame = (0 480; 320 49); opaque = NO; tag = 89364833; layer = <CALayer: 0x5a6d200>>
   |    |    | <UIButton: 0x5a6d580; frame = (0 0; 64 49); opaque = NO; layer = <CALayer: 0x5a6d660>>
   |    |    |    | <UIImageView: 0x5c35b20; frame = (0 0; 63 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35b50>>
   |    |    | <UIButton: 0x5a63480; frame = (64 0; 64 49); opaque = NO; tag = 1; layer = <CALayer: 0x5a66170>>
   |    |    |    | <UIImageView: 0x5c35aa0; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35ad0>>
   |    |    | <UIButton: 0x5a6da30; frame = (128 0; 64 49); opaque = NO; tag = 2; layer = <CALayer: 0x5a6dac0>>
   |    |    |    | <UIImageView: 0x5c35a20; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35a50>>
   |    |    | <UIButton: 0x5a6dc60; frame = (192 0; 64 49); opaque = NO; tag = 3; layer = <CALayer: 0x5a6dcf0>>
   |    |    |    | <UIImageView: 0x5c359a0; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c359d0>>
   |    |    | <UIButton: 0x5a6de90; frame = (256 0; 64 49); opaque = NO; tag = 4; layer = <CALayer: 0x5a6df20>>
   |    |    |    | <UIImageView: 0x5c358c0; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35970>>

以下是失败场景的视图层次结构:

<UIWindow: 0x5a4c7c0; frame = (0 0; 320 480); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x5a4ca30>>
   | <UILayoutContainerView: 0x5a591b0; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x5a59230>>
   |    | <UITransitionView: 0x5a59c00; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x5a59ca0>>
   |    |    | <UIViewControllerWrapperView: 0x5a6e960; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x5a6e9e0>>
   |    |    |    | <UILayoutContainerView: 0x5a5bb70; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x5a5bbc0>>
   |    |    |    |    | <UINavigationTransitionView: 0x5a5c290; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x5a19400>>
   |    |    |    |    |    | <UIViewControllerWrapperView: 0x5ae49f0; frame = (0 20; 320 411); layer = <CALayer: 0x5ae4870>>
   |    |    |    |    |    |    | <UIView: 0x5abcba0; frame = (0 0; 320 411); layer = <CALayer: 0x5a8ff50>>
   |    |    |    |    |    |    |    | <CaptureAuxMenu: 0x5ac6850; frame = (0 480; 320 49); layer = <CALayer: 0x5ac68e0>>
   |    |    |    |    |    |    |    |    | <UIImageView: 0x5ac6a50; frame = (0 0; 320 49); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5ac6a80>>
   |    |    |    |    |    |    |    |    | <UIButton: 0x5ac67c0; frame = (18 7; 80 31); opaque = NO; layer = <CALayer: 0x5ac6b80>>
   |    |    |    |    |    |    |    |    |    | <UIImageView: 0x5acf910; frame = (0 0; 80 31); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5acf940>>
   |    |    |    |    |    |    |    |    | <UIButton: 0x5ac7ed0; frame = (116 7; 80 31); opaque = NO; layer = <CALayer: 0x5ac7b50>>
   |    |    |    |    |    |    |    |    |    | <UIImageView: 0x5acf890; frame = (0 0; 80 31); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5acf8c0>>
   |    |    |    |    |    |    |    |    | <UIButton: 0x5ac91f0; frame = (285 10; 25 25); opaque = NO; layer = <CALayer: 0x5ac8e70>>
   |    |    |    |    |    |    |    |    |    | <UIImageView: 0x5acf810; frame = (0 0; 25 25); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5acf840>>

   |    | <UITabBar: 0x5a59560; frame = (0 431; 320 480); hidden = YES; autoresize = W+TM; layer = <CALayer: 0x5a59600>>
   |    |    | <UITabBarButton: 0x5a638f0; frame = (2 1; 60 479); opaque = NO; layer = <CALayer: 0x5a660a0>>
   |    |    |    | <UITabBarSelectionIndicatorView: 0x5a6e250; frame = (0 2; 60 475); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6e280>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a662a0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a66360>>
   |    |    |    | <UITabBarButtonLabel: 0x5a63ba0; frame = (16 465; 28 13); text = 'string'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a63990>>
   |    |    | <UITabBarButton: 0x5a660d0; frame = (66 1; 60 479); opaque = NO; layer = <CALayer: 0x5a674a0>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a663c0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a66410>>
   |    |    |    | <UITabBarButtonLabel: 0x5a66cc0; frame = (16 465; 28 13); text = 'string'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a665e0>>
   |    |    | <UITabBarButton: 0x5a65990; frame = (130 1; 60 479); opaque = NO; layer = <CALayer: 0x5a68140>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a689c0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a68170>>
   |    |    |    | <UITabBarButtonLabel: 0x5a696b0; frame = (16 465; 28 13); text = 'string'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a68ba0>>
   |    |    | <UITabBarButton: 0x5a68420; frame = (194 1; 60 479); opaque = NO; layer = <CALayer: 0x5a697d0>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a6abf0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6ac40>>
   |    |    |    | <UITabBarButtonLabel: 0x5a6af20; frame = (8 465; 44 13); text = 'FRIENDS'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a678c0>>
   |    |    | <UITabBarButton: 0x5a6a5a0; frame = (258 1; 60 479); opaque = NO; layer = <CALayer: 0x5a6b230>>
   |    |    |    | <UITabBarSwappableImageView: 0x5a6b9b0; frame = (6 218; 48 32); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6b260>>
   |    |    |    | <UITabBarButtonLabel: 0x5a677c0; frame = (8 465; 44 13); text = 'PROFILE'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5a6b3d0>>
   |    | <UIImageView: 0x5a6b850; frame = (0 480; 320 49); opaque = NO; tag = 89364833; layer = <CALayer: 0x5a6d200>>
   |    |    | <UIButton: 0x5a6d580; frame = (0 0; 64 49); opaque = NO; layer = <CALayer: 0x5a6d660>>
   |    |    |    | <UIImageView: 0x5c35b20; frame = (0 0; 63 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35b50>>
   |    |    | <UIButton: 0x5a63480; frame = (64 0; 64 49); opaque = NO; tag = 1; layer = <CALayer: 0x5a66170>>
   |    |    |    | <UIImageView: 0x5c35aa0; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35ad0>>
   |    |    | <UIButton: 0x5a6da30; frame = (128 0; 64 49); opaque = NO; tag = 2; layer = <CALayer: 0x5a6dac0>>
   |    |    |    | <UIImageView: 0x5c35a20; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35a50>>
   |    |    | <UIButton: 0x5a6dc60; frame = (192 0; 64 49); opaque = NO; tag = 3; layer = <CALayer: 0x5a6dcf0>>
   |    |    |    | <UIImageView: 0x5c359a0; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c359d0>>
   |    |    | <UIButton: 0x5a6de90; frame = (256 0; 64 49); opaque = NO; tag = 4; layer = <CALayer: 0x5a6df20>>
   |    |    |    | <UIImageView: 0x5c358c0; frame = (0 0; 64 49); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5c35970>>

我能看到的唯一明显区别是在这两种情况下的第 7 行和第 8 行。您将看到 UIViewControllerWrapperView 和子 UIView 具有不同的框架,但我不太确定为什么会出现问题,因为我不确定对应于哪个 UIView,而且我在 UIViewControllerWrapperView 上找不到任何文档。

我正在使用以下代码来交换标签栏:

- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    [AppHelpers hideTabBarController:self.tabBarController withHidden:YES];
    [self showCaptureTabBar];


+ (void) hideTabBarController:(UITabBarController *)tbc withHidden:(BOOL)hide 

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    for(UIView *view in tbc.view.subviews)
           
        if([view isKindOfClass:[UIImageView class]])
        
            if (hide) 
                [view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
             else 
                [view setFrame:CGRectMake(view.frame.origin.x, 431, view.frame.size.width, view.frame.size.height)];
            
        else 
            if (hide) 
                // When hiding the tabbarcontroller, the view should be full height
                [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
             else 
                // When showing the tabbarcontroller, the view needs to leave 49px of room for it at the bottom
                [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 431)];
            
        
    

    [UIView commitAnimations];  


- (void)showCaptureTabBar 
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1];
    [captureTabBar setFrame:CGRectMake(captureTabBar.frame.origin.x, 412.0f, captureTabBar.frame.size.width, captureTabBar.frame.size.height)];
    [UIView commitAnimations];

任何关于为什么可以禁用按钮以便我可以尝试其他调试的想法将不胜感激。有点撞墙了

【问题讨论】:

【参考方案1】:

如果您的包装器视图较小,那肯定会导致问题。特别是如果包装器小于其中的所有 UI 元素。 UIViews 仍然可以显示超出其框架的元素,但用户交互不会超出其框架。

要查看这是否是问题,请尝试在包装器上将“剪辑子视图”的属性设置为“是”,看看您是否仍然可以看到工具栏。如果您看不到工具栏,则应将包装器做得更大,以便整个工具栏可以进行用户交互。

【讨论】:

正是如此。我在上面指出,在失败的情况下,包装器短了 49px,这正是我的工具栏的大小。我需要知道的是为什么会发生这种情况,以便我可以修复它。我无法提供有关如何计算包装器视图尺寸的任何信息,但它的父级是全屏,所以我不确定为什么不会这样。 你试过在 viewDidLoad 中调用 hideTabBarController 吗?【参考方案2】:

如何在单个 beginAnimations/endAnimations 上下文中进行隐藏/显示?

- (void)viewDidAppear:(BOOL)animated 
 [super viewDidAppear:animated];

 [UIView beginAnimations:@"firstAnimation" context:NULL];
 [UIView setAnimationDuration:0.3];
 [AppHelpers hideTabBarController:self.tabBarController withHidden:YES];

 [UIView beginAnimations:@"secondAnimation" context:NULL];
 [UIView setAnimationDuration:1.0];
 [self showCaptureTabBar];

 [UIView commitAnimations];
 [UIView commitAnimations];


你试过吗?当然,你应该从这两种方法中删除动画......

这样我们嵌套了两个动画...

旧答案:

我不知道这是否有帮助,但您为什么不尝试隐藏/显示设置 hidden 属性的子视图?

        if (hide) 
            view.hide = YES;
         else 
            view.hide = NO;
        

最后,如果这不起作用,一种 hack(但我不知道它是否有效)可能如下:在 viewWillAppear 中进行交换,但不要顺序调用 hideTabBarControllershowCaptureTabBar ;而是尝试安排第二个方法以 0 延迟执行(这意味着执行 hideTabBarController,然后当控制流返回主循环时,执行 showCaptureTabBar):

[AppHelpers hideTabBarController:self.tabBarController withHidden:YES];
[self performSelector:@selector(showCaptureTabBar) withObject:nil afterDelay:0];

实际上,由于hideTabBarController 动画持续 0.3 秒,您可以指定延迟为 0.3,以防这两个动画相互干扰而不起作用。

【讨论】:

我目前的 hack 是在一个非常小的延迟后显示,但 IMO 这并不是真正的解决方案,它是一个 hack。 确实,我自己为此使用了“hack”这个词......也请参阅我的编辑

以上是关于为啥我的 TabBar 按钮在我第一次加载视图控制器时被禁用?的主要内容,如果未能解决你的问题,请参考以下文章

隐藏 TabBar 并在按钮单击时显示 NavigationController 工具栏

视图控制器仅在第一次正确加载图像

如何使用子视图控制器中的按钮单击更改 tabBar 项目标题

iOS:Tabbar - 加载选项卡的默认状态

加载新的 TabBar 视图时如何卸载 TabBar 视图?

关闭 3 层模态视图