你可能需要注意的细节(一) —— 关于UITabBarController的子控制器生命周期的问题

版本记录

版本号 时间
V1.0 2017.10.21

前言

目前市面上的APP架构基本都是一样的,都是UITabBarController作为根控制器,然后添加UINavigationController作为子控制器,然后再添加几个主页控制器,作为导航的根控制器。这里有一个问题就是子控制器的生命周期问题。

问题引出

关于注意UITabBarController子控制器生命周期的问题,还是在iOS11以后,在iOS11正式版出来以后,我就发现一个问题,凡是从几个主页面到二级页面的控制器,UITabBar都会先显示然后隐藏,做大约0.5s的一个动画,于是,我就要修改,想到第一个方案就是生命周期方法中强制隐藏和显示UITarBar。

这里我就在项目中- (void)viewWillAppear:(BOOL)animated中强制显示和在- (void)viewWillDisappear:(BOOL)animated中进行强制隐藏,但是发现还是不多,通过打断点,我发现原来是生命周期的问题。


素材准备

下面我们就看一下准备的实现素材。下面直接看代码。

1. AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    JJTabBarVC *tabBarVC = [[JJTabBarVC alloc] init];
    self.window.rootViewController = tabBarVC;
    [self.window makeKeyAndVisible];
    return YES;
}
2. JJTabBarVC.m
#import "JJTabBarVC.h"
#import "ZBLivelistController.h"
#import "ZBVideoAlbumVC.h"
#import "ZBShortVideoVC.h"

@interface JJTabBarVC ()

@end

@implementation JJTabBarVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self addChildViewController];
}

#pragma mark - Object Private Function

- (void) addChildViewController
{
    [self addChirdViewControllerWithClass:[[ZBLivelistController alloc] init] andTitle:@"直播" andImage:[UIImage imageNamed:@"TabBar_LiveTab_normal"] selectImage:[UIImage imageNamed:@"TabBar_LiveTab_normal"]];
    [self addChirdViewControllerWithClass:[[ZBVideoAlbumVC alloc] init] andTitle:@"首页" andImage:[UIImage imageNamed:@"TabBar_HomeTab_normal"] selectImage:[UIImage imageNamed:@"TabBar_HomeTab_normal"]];
    [self addChirdViewControllerWithClass:[[ZBShortVideoVC alloc] init] andTitle:@"短视频" andImage:[UIImage imageNamed:@"TabBar_shortVideoTab_normal"] selectImage:[UIImage imageNamed:@"TabBar_shortVideoTab_normal"]];
}

- (void) addChirdViewControllerWithClass:(UIViewController *)vc andTitle:(NSString *)title andImage:(UIImage *)image selectImage:(UIImage *)selectImage
{
    vc.title = title;
    vc.tabBarItem.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    vc.tabBarItem.selectedImage = [selectImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
    [self addChildViewController:nav];
}

@end
3. ZBLivelistController.m
#import "ZBLivelistController.h"

@interface ZBLivelistController ()

@end

@implementation ZBLivelistController

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    self.tabBarController.tabBar.hidden = NO;
    
    NSLog(@"ZBLivelistController --- viewWillAppear");
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    self.tabBarController.tabBar.hidden = YES;
    
    NSLog(@"ZBLivelistController --- viewWillDisappear");
}

@end
4. ZBVideoAlbumVC.m
#import "ZBVideoAlbumVC.h"

@interface ZBVideoAlbumVC ()

@end

@implementation ZBVideoAlbumVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    self.tabBarController.tabBar.hidden = NO;
    
    NSLog(@"ZBVideoAlbumVC --- viewWillAppear");
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    self.tabBarController.tabBar.hidden = YES;
    
    NSLog(@"ZBVideoAlbumVC --- viewWillDisappear");
}

@end
5. ZBShortVideoVC.m
#import "ZBShortVideoVC.h"

@interface ZBShortVideoVC ()

@end

@implementation ZBShortVideoVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    self.tabBarController.tabBar.hidden = NO;
    
    NSLog(@"ZBShortVideoVC --- viewWillAppear");
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    self.tabBarController.tabBar.hidden = YES;
    
    NSLog(@"ZBShortVideoVC --- viewWillDisappear");
}

@end

运行起来如下图所示。

你可能需要注意的细节(一) —— 关于UITabBarController的子控制器生命周期的问题_第1张图片

但是测试一下,我们就会发现,当点击短视频,再点击直播页面的时候,tabBar没有了,所以我们看打印输出。

你可能需要注意的细节(一) —— 关于UITabBarController的子控制器生命周期的问题_第2张图片
2017-10-22 00:22:26.648393+0800 testDemo[6569:592943] ZBLivelistController --- viewWillAppear
2017-10-22 00:22:28.486030+0800 testDemo[6569:592943] ZBLivelistController --- viewWillDisappear
2017-10-22 00:22:28.504998+0800 testDemo[6569:592943] ZBShortVideoVC --- viewWillAppear
2017-10-22 00:22:30.118026+0800 testDemo[6569:592943] ZBLivelistController --- viewWillAppear
2017-10-22 00:22:30.119026+0800 testDemo[6569:592943] ZBShortVideoVC --- viewWillDisappear

这里就会发现,当我们点击短视频,在点击直播,就会发现,程序会先调用直播页面ZBLivelistController --- viewWillAppear,而后调用短视频页面的ZBShortVideoVC --- viewWillDisappear,这就导致了UITabBar被隐藏掉了,为什么会这样呢,和我们平时看到的控制器是不一样的,我们平时看到的都是先调用要消失控制器的willDisappear,后调用要出现的控制器视图的willAppear方法。在这里就是完全反的。这里我们怎么解决这个问题呢?


问题解决

有了上面的问题,我们就要解决,最简单直接的方法就是在三个子控制器中多加一个方法,如下所示。

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    self.tabBarController.tabBar.hidden = NO;
}

这样就解决了生命周期的问题,解决隐藏时出现的错误。这样就可以在视图出现的时候就不要隐藏UITabBar,解决了这个问题。

后记

未完,待续~~~

你可能需要注意的细节(一) —— 关于UITabBarController的子控制器生命周期的问题_第3张图片

你可能感兴趣的:(你可能需要注意的细节(一) —— 关于UITabBarController的子控制器生命周期的问题)