I'm trying to use a splitview inside a TabBar. By now I have a SplitView in my first TabBarItem. My problem comes when I try to access to a different DetailView or right view in the SplitViewController I have.
I'm trying to do it inside the didSelectRowAtIndexPath: of my Root (or Master) viewcontroller from the SplitView.
Here's the code, where I try to acces to my TabBarController from an AppDelegate object, and change the viewControllers array of my SplitView only changing the second view controller. I always get this crash error, saying that 2nd instance send is unrecognized: -[SecondViewController viewControllers]: unrecognized selector sent to instance 0x6852460
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//object AppDelegate
AppDelegate *myDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
//Objecte in Index 0 is my SplitVC
NSArray *barControllers = myDelegate.tabBarController.viewControllers;
if (indexPath.row == 0)
{
SplitVC *temporalSplit = [barControllers objectAtIndex:indexPath.row];
NSArray *mArray = temporalSplit.viewControllers;
FirstViewController *detail = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
UINavigationController *navigationDetail = [[UINavigationController alloc]initWithRootViewController:detail];
temporalSplit.delegate = detail;
temporalSplit.viewControllers = [[NSArray alloc] initWithObjects:[mArray objectAtIndex:0], navigationDetail, nil];
myDelegate.tabBarController.viewControllers = [NSArray arrayWithObjects:temporalSplit.viewControllers, [barControllers objectAtIndex:1], nil];
}
else if (indexPath.row == 1)
{
SplitVC *temporalSplit = [barControllers objectAtIndex:indexPath.row];
NSArray *mArray = temporalSplit.viewControllers;
Detail2VC *detail = [[Detail2VC alloc]initWithNibName:#"Detail2VC" bundle:nil];
UINavigationController *navigationDetail = [[UINavigationController alloc]initWithRootViewController:detail];
temporalSplit.delegate = detail;
temporalSplit.viewControllers = [[NSArray alloc] initWithObjects:[mArray objectAtIndex:0], navigationDetail, nil];
myDelegate.tabBarController.viewControllers = [NSArray arrayWithObjects:[barControllers objectAtIndex:0], temporalSplit, nil];
}
[myDelegate release];
}
And my AppDelegate code (that works without problems):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
// Override point for customization after application launch.
NSMutableArray *controllersBar = [[NSMutableArray alloc]init];
UIViewController *viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil] autorelease];
for (int i = 0; i<2; i++)
{
if(i == 0)
{
_firstViewController = [[[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil] autorelease];
_masterApp = [[MasterVC alloc]initWithNibName:#"MasterVC" bundle:nil];
_masterApp.firstViewController = _firstViewController;
_firstViewController.mastervc = _masterApp;
UINavigationController *navigationMaster = [[UINavigationController alloc]initWithRootViewController:_masterApp];
UINavigationController *navigationDetail = [[UINavigationController alloc]initWithRootViewController:_firstViewController];
_splitVC = [[SplitVC alloc] initWithNibName:nil bundle:nil];
//_splitVC.tabBarItem = controller.tabBarItem;
_splitVC.viewControllers = [NSArray arrayWithObjects:navigationMaster, navigationDetail, nil];
_splitVC.delegate = _firstViewController;
[controllersBar addObject:_splitVC];
}
else if (i == 1)
{
[controllersBar addObject:viewController2];
}
}
//self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
_tabBarController.viewControllers = controllersBar;
_tabBarController.selectedIndex = 0;
_tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
What am I doing wrong? Any help or suggestion is welcome.
Thanks to all in advance.
Split view controller MUST be root level controllers:
UISplitviewcontroller not as a rootview controller
If not, you can apparently get all sorts of strange things happening.
Related
When I add a view controller embedded by navigation controller, to a tab bar, its icon + title disappear briefly when coming back to the More tab.
However when the view controller is added as such, the icon+image are okay and don't disappear.
I've tried many things already, and am out of options. Any ideas?
Here's my AppDelegate code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.tabBarController = [[UITabBarController alloc] init];
// Must be placed here, just before tabs are added. Otherwise navigation bar
// will overlap with status bar.
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[self addViewControllersToTabBar];
self.window.rootViewController = self.tabBarController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)addViewControllersToTabBar
{
NSArray* tabBarClassNames =
#[
NSStringFromClass([FirstViewController class]),
NSStringFromClass([SecondViewController class]),
NSStringFromClass([FirstViewController class]),
NSStringFromClass([FirstViewController class]),
NSStringFromClass([FirstViewController class]),
NSStringFromClass([SecondViewController class]),
NSStringFromClass([FirstViewController class]),
];
NSMutableArray* viewControllers = [NSMutableArray array];
for (NSString* className in tabBarClassNames)
{
UIViewController* viewController = [[NSClassFromString(className) alloc] init];
UINavigationController* navigationController;
navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[viewControllers addObject:navigationController];
}
[viewControllers addObject:[[FirstViewController alloc] init]]; // This one is fine.
self.tabBarController.viewControllers = viewControllers;
self.tabBarController.selectedViewController = viewControllers[2];
}
and the view controllers are literally nothing more than:
#implementation SecondViewController
- (instancetype)init
{
if (self = [super init])
{
self.title = #"second";
self.tabBarItem.image = [UIImage imageNamed:#"second.png"];
}
return self;
}
#end
Holy shit, spent so much time on this bug, but here's my workaround. Instead of:
navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
I created my own NavigationController as subclass of UINavigationController:
#implementation NavigationController
- (instancetype)initWithRootViewController:(UIViewController*)rootViewController
{
if (self = [super initWithRootViewController:rootViewController])
{
NSString* className = NSStringFromClass([rootViewController class]);
NSString* name = [className stringByReplacingOccurrencesOfString:#"ViewController" withString:#""];
self.tabBarItem.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#Tab.png", name]];
}
return self;
}
#end
and then do:
navigationController = [[NavigationController alloc] initWithRootViewController:viewController];
Prerequisite is that tab images have the same base name as the view controller class name, which was already the case in my app.
I was setting self.tabBarItem.image inside the view controllers' init method, and this seems to cause the effect I was seeing. So in addition to using my own navigation controller, I also simply deleted setting the tabBarItem in each individual view controller.
I have encountered a very strange behavior, when I implemented navigationController.
I have a LogInViewController with an UITableView,where cells are populated like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
return cellUsername;
}
if (indexPath.row == 1){
return cellPassword;
}
else{
return nil;
}
}
cellUsername and cellPassword are Cells which I created on .xib..
And when i add this LogInViewController as a rootViewController in my appDelegate it works fine!
I wanted to implement a navigationController, so I created RootViewController, with navController #property and in my appDelagate i called it like this
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
RootViewController *rootView = [[RootViewController alloc]init];
rootView.navController = [[UINavigationController alloc] initWithRootViewController:rootView];
self.window.rootViewController = rootView.navController;
[self.window makeKeyAndVisible];
return YES;
And in my RootViewController on viewDidLoad I have this code:
[super viewDidLoad];
self.navController = [[UINavigationController alloc]init];
LogInViewController *loginView = [[LogInViewController alloc]init];
[[self navigationController] pushViewController:loginView animated:YES];
It opens my LogInViewController,but only the first cell,cellUsername is added to my UiTableView, what is wrong?
Am still a beginner,so I might be missing something stupid probably.. but it works wihout navigationController,so am pretty confused..
Thank you!
I'm not sure if this has anything to do with your problem, but you shouldn't be using this line in your viewDidLoad:
self.navController = [[UINavigationController alloc]init];
Your RootViewController is already embedded in a navigation controller, so you can just use self.navigationController to get a reference to it.
I'm also not sure about this code, it may be ok, but it's not the way it's usually done:
RootViewController *rootView = [[RootViewController alloc]init];
rootView.navController = [[UINavigationController alloc] initWithRootViewController:rootView];
self.window.rootViewController = rootView.navController;
The usual way to do it is like this:
RootViewController *rootView = [[RootViewController alloc]init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:rootView];
self.window.rootViewController = nav;
in AppDelegate file
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
RootViewController *rootView = [[RootViewController alloc]init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootView];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
Further there is no need to create another navigationController in the viewDidLoad of the RootViewController class
I have a login screen for a UITabBar application where users are divided into two categories. I want to show a certain tab for one type of user and other tabs for the other type of user. Does anyone have an idea of where to start?
In one of my app i have used this code to set tabbarcontroller in between app
First create login screen without tabbarcontroller
This is just a example modify according your condition
define tabbar controller in your AppDelegate.m
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate=self;
self.tabBarController.selectedIndex=0;
self.tabBarController.delegate=self;
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
//NSUInteger index=[[tabBarController viewControllers] indexOfObject:viewController];
// return YES;
}
Apply below code where you login and push your controller with tab bar controller
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
UIViewController *viewController1 = [[GeneralViewController alloc] initWithNibName:#"GeneralViewController" bundle:nil];
UIViewController *viewController2 = [[MiscQuotationController alloc] initWithNibName:#"MiscQuotationController" bundle:nil];
UIViewController *viewController4 = [[QuotationListController alloc] initWithNibName:#"QuotationListController" bundle:nil];
UIViewController *viewController5 = [[ChargesViewController alloc] initWithNibName:#"ChargesViewController" bundle:nil];
UIViewController *viewController7 = [[SalesPartViewController alloc] initWithNibName:#"SalesPartViewController" bundle:nil];
/// tab button title
viewController1.title = #"Basic information";
viewController2.title = #"Misc Quotation";
viewController4.title = #"Quotation Line";
viewController5.title = #"Charges";
viewController7.title = #"Sales Part Stock";
// tab button Images
viewController1.tabBarItem.image = [UIImage imageNamed:#"general.png"];
viewController2.tabBarItem.image = [UIImage imageNamed:#"misle.png"];
viewController4.tabBarItem.image = [UIImage imageNamed:#"history.png"];
viewController5.tabBarItem.image = [UIImage imageNamed:#"charges.png"];
viewController7.tabBarItem.image = [UIImage imageNamed:#"shoebox.png"];
delegate.tabBarController = [[UITabBarController alloc] init];
delegate.tabBarController.selectedIndex = 0;
// Write your condition of user here
if(user == admin){
delegate.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController4, viewController5, viewController7, nil];
}
else{
delegate.tabBarController.viewControllers = [NSArray arrayWithObjects: viewController2, viewController4, viewController5, viewController7, nil];
}
delegate.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, viewController4, viewController5, viewController7, nil];
delegate.tabBarController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self.navigationController pushViewController:delegate.tabBarController animated:YES];
I have a UITabBar with 2 UINavigationController created in my AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
UINavigationController *navController1, *navController2;
PolyPage *viewController1 = [[PolyPage alloc] init];
PolyPage *viewController2 = [[PolyPage alloc] init];
navController1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
navController2 = [[UINavigationController alloc] initWithRootViewController:viewController2];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:navController1, navController2, nil];
...
return YES
}
My view controllers are the same. In PolyPage.m I have the method :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:CGPointMake(150, self.tableView.contentOffset.y + 240)];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
imageViewer = [[ImageViewer alloc] initWithDataSource:[NSArray arrayWithObject:cell.imageView.image]];
[self.navigationController presentModalViewController:imageViewer animated:YES];
}
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
This method shows my modal view controller only with the first navigation controller in the UITabBar.
I would like to make it work with both navigation controllers.
![I am creating a tab bar controller programmatically:
tabBarController = [[UITabBarController alloc] init];
FirstViewController* vc1 = [[FirstViewController alloc] init];
SecondViewController* vc2 = [[SecondViewController alloc] init];
vc1.title = #"Dallas";//[[NSUserDefaults standardUserDefaults] objectForKey:#"Citynamefrmhome"];
vc1.tabBarItem.image = [UIImage imageNamed:#"Dealss.png"];
vc2.title = #"My Vouchers";
vc2.tabBarItem.image = [UIImage imageNamed:#"nav_voucher_S.png"];
NSArray* controllers = [NSArray arrayWithObjects:vc1,vc2, nil];
tabBarController.viewControllers = controllers;
[self.view addSubview:tabBarController.view];
[vc1 release];
[vc2 release];
if I load it when the app starts, it looks great (look at figure 1):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
autoMagically = [[AutoMagically alloc] initWithNibName:nil bundle:nil];
//self.window.rootViewController = self.dummyView;
[self.window addSubview:autoMagically.view];
[self.window makeKeyAndVisible];
return YES;
}
if I load it when a button is clicked, the way i wanna do it, it looks like figure 2. See how the titles arent showing and the buttons seem to be getting cutoff:
- (void)LoadView
{
AutoMagically *autoMagic = [[AutoMagically alloc]
initWithNibName:nil bundle:nil];
self.autoMagically = autoMagic;
[self.view insertSubview:autoMagic.view atIndex:0];
[autoMagic release];
}
Does anyone know why this is behaving like this?]1
You can call
[[[self.parentViewController.tabBarController.tabBar.items objectAtIndex:/*a number based on what tab it was ex: 2*/]setTitle:#"string"];
in your -viewDidLoad or -awakeFromNib methods. It might be better to use the latter instead of the former.