sunsunai sunsunai - 4 months ago 41
Objective-C Question

Always display tabBarController when pushed to any viewController

I have 1 UITabbarController with 3 ViewControllers belong to its named aVC-bVC-cVC(VC = ViewController). Then I have 1 MenuSideBar have others 3 ViewControllers named dVC-eVC-fVC.

All I want is whenever I push to dVC or eVC or fVC my UITabbarController always display. How I can do that ? I really stuck at this point. I have to try many ways even custom a tabbarController myself but still not working.

Please help me. I really need help on this case.

Very thank you.

Answer

I have made the sample demo for you in Objective C using SWRevealViewController as you had tagged that in your question. I have used the XCode 7.1.1 version. Make sure to open this demo in 7.x versions of XCode. This problem can also be solved by other side menu libraries like MFSideMenu etc

Here is the link of the demo sample made by me according to your requirements.
https://github.com/RajanMaheshwari/TabBarControllerApp

EXPLANATION:

In order to keep a tab bar always in your app you have to add a TabBar on every controller which is not a added viewController of UITabBarController. In my sample demo I have taken the various Controllers

1.LeftSideViewController - which will be the left side panel for whole app.

2.MainTabBarViewController - which will be the UITabBarController subclass and it will be connected to two other view controllers which will be the part of MainTabBarViewController.
----a.TabFirstViewController
----b.TabSecondViewController

3.FirstViewController- which will be the one that will from LeftSideViewController's table view and has its own UITabBar added.

4.SecondViewController- which will be the one that will from LeftSideViewController's table view and has its own UITabBar added.

Import the SWRevealViewController folder.
In your AppDelegate's didFinishLaunchingWithOptions method we need to make the root view controller as the MainTabBarViewController.

AppDelegate.h

#import <UIKit/UIKit.h>
#import "SWRevealViewController.h"

@interface AppDelegate : UIResponder<UIApplicationDelegate,SWRevealViewControllerDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) SWRevealViewController *viewController;

@end

AppDelegate.m

#import "AppDelegate.h"
#import "LeftSideViewController.h"
#import "SWRevealViewController.h"
#import "MainTabBarViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate
@synthesize window = _window;
@synthesize viewController = _viewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

   //Here Adding some notification observers which will be fired whenvever a tabbar index in clicked of the viewcontrollers whose parent is not UITabBarController class and the left side menu ones too.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backToTabIndexControllerFirst) name:@"backToTabIndexControllerFirst" object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backToTabIndexControllerSecond) name:@"backToTabIndexControllerSecond" object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(firstVCWithoutNAV) name:@"firstVCWithoutNAV" object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(secondVCWithoutNAV) name:@"secondVCWithoutNAV" object:nil];

    UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window = window;
        UIStoryboard* storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:@"LeftSideViewController"];
        MainTabBarViewController *mainTabBarController = [storyBoard instantiateViewControllerWithIdentifier:@"MainTabBarViewController"];
        SWRevealViewController *mainRevealController =  [[SWRevealViewController alloc]
                                                    initWithRearViewController:leftSideController frontViewController:mainTabBarController];

    mainRevealController.delegate = self;
    self.viewController = mainRevealController;
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    return YES;
}

Methods Definations of all observers added

AppDelegate.m

-(void)firstVCWithoutNAV{

    self.window.rootViewController = nil;
    UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UINavigationController * firstVC = [storyBoard instantiateViewControllerWithIdentifier:@"FirstNAV"];
    LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:@"LeftSideViewController"];
    SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
                                                    initWithRearViewController:leftSideController frontViewController:firstVC];

    mainRevealController.delegate = self;

    self.viewController = mainRevealController;

    self.window.rootViewController = self.viewController;
}

-(void)secondVCWithoutNAV{

    self.window.rootViewController = nil;
    UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UINavigationController * secondVC = [storyBoard instantiateViewControllerWithIdentifier:@"SecondNAV"];
    LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:@"LeftSideViewController"];
    SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
                                                    initWithRearViewController:leftSideController frontViewController:secondVC];

    mainRevealController.delegate = self;

    self.viewController = mainRevealController;

    self.window.rootViewController = self.viewController;

}

-(void)backToTabIndexControllerFirst{
    UIStoryboard* storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

    LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:@"LeftSideViewController"];


    MainTabBarViewController *mainTabBarController = [storyBoard instantiateViewControllerWithIdentifier:@"MainTabBarViewController"];

    SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
                                                    initWithRearViewController:leftSideController frontViewController:mainTabBarController];

    mainRevealController.delegate = self;

    self.viewController = mainRevealController;

    self.window.rootViewController = self.viewController;
}

-(void)backToTabIndexControllerSecond{

    UIStoryboard* storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

    LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:@"LeftSideViewController"];


    MainTabBarViewController *mainTabBarController = [storyBoard instantiateViewControllerWithIdentifier:@"MainTabBarViewController"];

    //To make selected index as the one which is clicked from tab bar
    mainTabBarController.selectedIndex = 1;
    SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
                                                    initWithRearViewController:leftSideController frontViewController:mainTabBarController];

    mainRevealController.delegate = self;

    self.viewController = mainRevealController;

    self.window.rootViewController = self.viewController;
}

In the Controllers which have no UITabBarController parent class, we will add a tabBar and set tabBar's delegate to self and add the tabBar's didSelectItem delegate method.

FirstViewController.h

#import <UIKit/UIKit.h>

@interface FirstViewController : UIViewController<UITabBarDelegate>
@property (weak, nonatomic) IBOutlet UITabBar *tabBar;

@end

FirstViewController.m

#import "FirstViewController.h"
#import "SWRevealViewController.h"
@interface FirstViewController ()

@end

@implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    SWRevealViewController *revealController = [self revealViewController];

    [self.view addGestureRecognizer:revealController.panGestureRecognizer];


    UIBarButtonItem* revealButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"reveal-icon.png"] style:UIBarButtonItemStylePlain target:revealController action:@selector(revealToggle:)];

    self.navigationItem.leftBarButtonItem = revealButtonItem;

    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{
    NSUInteger indexOfTab = [[tabBar items] indexOfObject:item];
    NSLog(@"Tab index = %u", (int)indexOfTab);

    if(indexOfTab == 0){
        [[NSNotificationCenter defaultCenter] postNotificationName:@"backToTabIndexControllerFirst" object:nil];
    }else{
        [[NSNotificationCenter defaultCenter] postNotificationName:@"backToTabIndexControllerSecond" object:nil];
    }
}

The notifications fired from here will change the root controller of the application.

Similarly we will code for SecondViewController

Assuming that there is a Table For selection of various other controllers from LeftSidePanel, we will add the tableView's didSelectRowAtIndexPath method as follows:

LeftSideViewController.m

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    SWRevealViewController *revealController = self.revealViewController;
    [revealController revealToggleAnimated:YES];

    // Used this just to show the animation completion and then changing the root
    [self performSelector:@selector(changeControllers:) withObject:indexPath afterDelay:0.3];

}

-(void)changeControllers:(NSIndexPath*)indexPath{

    if(indexPath.row == 0){
        [[NSNotificationCenter defaultCenter] postNotificationName:@"firstVCWithoutNAV" object:nil];
    }else{
        [[NSNotificationCenter defaultCenter] postNotificationName:@"secondVCWithoutNAV" object:nil];
    }
}

We can also use other libraries as I already stated for side panel. Example
https://github.com/mikefrederick/MFSideMenu

Hope this solves the problem!

Comments