custom TabBar loses TabBarItem images

2019-09-20 13:25发布

问题:

I have made a custom UITabBar that is working very well, but I introduced a change to navigation and now i am having some serious issues. Here is what I have:

General Setup

TabBarController 
    NavbarController1 - TabBarItem1
        Links to: PeopleView
    NavbarController2 - TabBarItem2
        Links to: ContentView
    NavbarController3 - TabBarItem3
        Links to: ContentView //Same VC as TabBaritem 2.  

App Delegate - In my didFinishLaunchingWithOptions method I call a customizeTabBar method as follows

-(void) customizeTabBar
{

UITabBarController *tabVC = (UITabBarController *) self.window.rootViewController;
//Load Navigation Bar images
NSArray *unSelectedImages = [[NSArray alloc] initWithObjects:@"image1.jpg", @"image2.jpg", @"image3.jpg", @"image4.jpg", @"image5.jpg", nil];
NSArray *selectedImages = [[NSArray alloc] initWithObjects:@"image1_on.jpg", @"image2_on.jpg", @"image3_on.jpg", @"image4_on.jpg", @"image5_on.jpg", nil];

NSArray *items = tabVC.tabBar.items;

for (int idx = 0; idx < items.count; idx++)
{

    UITabBarItem *barItem = [items objectAtIndex:idx];
    barItem.tag = idx;
    UIImage *selectedImage = [UIImage imageNamed:[selectedImages objectAtIndex:idx]];
    UIImage *unSelectedImage = [UIImage imageNamed:[unSelectedImages objectAtIndex:idx]];


    UIEdgeInsets inset = {
        .top = 10,
        .left = 0,
        .bottom = -10,
        .right = 0
    };

    barItem.imageInsets = inset;

    [barItem setFinishedSelectedImage:selectedImage withFinishedUnselectedImage:unSelectedImage];
}

So far this is working beautifully.

Here is where the problem comes in. In order to get my TabBarItem3 to link to ContentView, I implemented the following code in my TabBarClass:

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {

if (viewController.tabBarItem.tag == 1 || viewController.tabBarItem.tag == 2 )
{
    // Validating if is necesarry to replace the TabBarController.ViewControllers
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

    MediaList *mediaView = [storyboard  instantiateViewControllerWithIdentifier:@"SB_MediaList"];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:mediaView];
    NSMutableArray *viewsArray = [NSMutableArray arrayWithArray:self.viewControllers];


    if (viewController.tabBarItem.tag == 1)
    {
        //Setting the specfic data for my instance for tabBarItem 1
        NSLog(@"Here we are in 1");
        [mediaView setContent:@"Personalized content/data for TabBarItem 1"];
    }
    else if (viewController.tabBarItem.tag == 2)
    {
        //Setting the specfic data for my instance for tabBarItem 2
        NSLog(@"Here we are in 2");
        [mediaView setContent:@"Personalized content/data for TabBarItem 2"];
    }
    [viewsArray replaceObjectAtIndex:viewController.tabBarItem.tag withObject:navigationController];
    self.viewControllers = viewsArray;

}
}

Upon execution of this code, I lose the images associated with my custom tab bar for items 2 or 3 (depending on which I select).

UPDATE

So, I moved my tab bar customization method out of my delegate and into a maintabbar class and I call it on viewdidload and I the meh hid didselectviewcontroller. This seems to solve the problem with missing images, but has created a bad side effect of flickering on the screen when I click either of hose items. I have tried different combinations of removing it from the viewdidload method as we'll, but still no luck..

回答1:

As I understand the purpose of this whole thing is to avoid having to create different classes for two tab bar items that will perform almost the same thing but with different data.

So fist, you have to defined a class capable of doing such thing, let's call it CommonClass. This class will have to have the necessary methods for doing a properly initialization. [I'm sure you have done this].

Then on your storyboard, you will still need to have two ViewController elements, each one as rootViewController of it's corresponding NavigationController.

I strongly recommend doing this way instead of trying to assign a new instance by code as we tried on: Linking to a view multiple times from tabar. Those two view controllers obviously belong to the same class CommonClass so you will still be reusing that class. In this way we won't have to alter the NavigationBar during the execution time which can be messy.

Then, you can send the necessary initialization information for your CommonClass having a method on your CommonClass that will load the appropiate information/data according to the selected tabBarItem, you can do that on the viewDidLoad method.

as the following:

- (void)viewDidLoad
{
    [super viewDidLoad];
    if (self.tabBarController.selectedIndex == 1) {
        [self customizeWithData:@"Specific data for my first instance"];
    } else if (self.tabBarController.selectedIndex == 2) {
        [self customizeWithData:@"Specific data for my second instance"];        
    }
}

In this way you will be doing the customization of your tab bar in just one part of your code and as you won't be altering it in execution time you won't need to customization in other parts causing flickering.