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!