How to pop the split view controller "DetailViewController?" - iphone

detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
[self.splitViewController.splitViewController viewWillDisappear:YES];
detailViewController.strDetailId = [teaserSectionOneArray objectAtIndex:indexValue] ;
NSMutableArray *viewControllerArray = [[NSMutableArray alloc] initWithArray:[[self.splitViewController.viewControllers objectAtIndex:1] viewControllers]];
[viewControllerArray removeAllObjects];
[viewControllerArray addObject:detailViewController];
[[self.splitViewController.viewControllers objectAtIndex:1] setViewControllers:viewControllerArray animated:NO];
[self.splitViewController.splitViewController viewWillAppear:YES];
[viewControllerArray release];
This code using for push to the detail view. How do I pop to another view controller in detail view when I click the button? Its not supported the [self.navigationController popViewControllerAnimated:YES];. How to handle this problem? Thanks in advance!

Wooooow thats NOT how you push a view controller on the stack of a navigationController !!
You don't have to call viewWillDisappear, viewWillAppear and such yourself ! You don't have to add the detailViewController to the splitViewController.viewControllers array yourself either!
What you need to do is this:
Make sure your UISplitViewController has a NavigationController as part of its detailViewController (namely the ViewController that is on the right of the screen should be an UINavigationController, not a regular UIViewController).
The rest is then easy as it works the same way as any regular UINavigationController. The fact that your UINavigationController is the right part of an UISplitViewController is not different than when you use an UINavigationController in any other context.
Simply use pushViewController:animated: and popViewControllerAnimated: methods of UINavigationController to push and pop your view controllers. Access your UINavigationController from your UISplitViewController using either a custom IBOutlet that you added to point to it, or by accessing (UINavigationController*)[self.splitViewController.viewControllers objectAtIndex:1].

Related

Subclassing UINavigationController for custom navigation between Views

I am making a small app with the following view hierarchy with UINavigationController:
Login -> Options -> three different views
The problem is that I would like to navigate between the last 3 views in the following manner:
1<->2
1<->3
2<->3
i.e. to be able to switch to any view from any other view, which reminds UITabViewController functionality. So, it is not hierarchical, it is any-to-any graph. To switch between views I will use buttons in the navigation bar.
The easiest way for me is to subclass UINavigationController, add properties that correspond to my views and implement methods for switching between these views (using pushViewController and popToRootViewController). These methods will be called from the views for switching (navigating).
However the reference says that UINavigationController is not intended for subclassing.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
What do you recommend me to do?
I'll keep the UINavigationController but instead of using the usual pushViewController:, switch views like this:
NSMutableArray *viewControllers = [self.navigationController.viewControllers mutableCopy];
// from here you can modify the order of controllers as much as you want
[viewControllers addObject:nextViewController];
[viewControllers removeObject:self];
[self.navigationController setViewControllers:viewControllers animated:YES];
If you don't want how the animation turns out, you can set animated:NO and either enclose setViewControllers: in an [UIView animate...] block, or add your own custom CAAnimation to the navigation controller's layer.
Use the below code to add a view controller to a navigation controller,
Navigating From first -> second
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
NSMutableArray *navigationarray = [[NSMutableArray alloc] initWithArray:self.navigationController.viewControllers];
[navigationarray removeAllObjects];
[navigationarray addObject:secondView];
self.navigationController.viewControllers = navigationarray;
Navigating From first -> third
ThirdViewController *thirdView = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
NSMutableArray *navigationarray = [[NSMutableArray alloc] initWithArray:self.navigationController.viewControllers];
[navigationarray removeAllObjects];
[navigationarray addObject:thirdView];
self.navigationController.viewControllers = navigationarray;
The above code will removes all the viewControllers from the Navigation Array and places a fresh View Controller
If u want to go to a particular view controller, then use the below code...
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES]
Change the index to ur view controller in the stack.

Can i take tabbar controller in view controller rather than delegate class?

I am using a UINavigation Controller in a delegate class. After navigating the two views class on the third view class I need a tabbar controller which can control three another ViewControllers and the tabbar should not be seen on first two view controllers. How can i do this ?
- (void)viewDidLoad
{
[super viewDidLoad];
self.title =#"Scan";
tabController =[[UITabBarController alloc]init];
ScanTicketView *scan =[[ScanTicketView alloc]initWithNibName:#"ScanTicketView" bundle:nil];
SearchView *search =[[SearchView alloc]initWithNibName:#"SearchView" bundle:nil];
HistoryView *history =[[HistoryView alloc]initWithNibName:#"HistoryView" bundle:nil];
tabController.viewControllers=[NSArray arrayWithObjects:scan,search,history, nil];
[self presentModalViewController:tabController animated:YES];
}
Follow my answer ... you can add and remove tabBar whenEver you want
link
Yes you can. See this link to an example
In your second view controller where you want to push to you third view(tab controller) do this
UITabBarController *tabBarController=[[UITabBarController alloc]init];
tabBarController.viewControllers=[NSArray arrayWithObjects:firstViewController,secondViewController,thirdViewController, nil];
//[self.navigationController pushViewController:tabBarController animated:YES];// this works too but since it seems to be against Apple's Human interface Guidelines you can present the view instead of pushing
[self presentModalViewController:tabBarController animated:NO];
Ideally TabBarcontroller should be the starting case of an app..but in rare cases where you want to present it in a viewcontroller follow ..
UITabBarController *tabBarController=[[UITabBarController alloc]init];
tabBarController.viewControllers=[NSArray arrayWithObjects:firstViewController,secondViewController,thirdViewController, nil];
[self presentModalViewController:tabBarController animated:NO];

Talking to A UITabBarController In Story boards

So In my app, I use a storyboard, and the initial viewController is a UITabBarController. What I want to do is when the app launches, I want to be able to set wheather the tabBarController has 3 items or 4. So in the appDel, I plan to check weather that user should see 3 or 4 tabs, and then the tabBarController should reflect that.
I tried subclassing the tabBarController, but the its not working:
#implementation TabBarController
-(id) init{
if ((self = [super init])) {
[[[[self tabBar] items] objectAtIndex:2] setEnabled:YES];
[[[[self tabBar] items] objectAtIndex:3] setEnabled:NO];
[[[[self tabBar] items] objectAtIndex:3] setHidden:YES];
}
return self;
}
#end
Any help would be apprciated.
Thanks in advance.
I'm thinking the easier (probably not best) way to do this is by having the TabBar controller not be the initial view controller and creating two tab bar controllers. From your initial view you can decide with tab bar controller you will show. You can also have the two tab bar controllers linked to the same tabs/viewcontrollers (the ones that are repeated between them).
In the initial view controller you add some code to know which segue you will perform and voila.
Something like this:
I am looking into a code solution to this though (seems interesting!). Will update if I find anything.
EDIT:
Here's the coded solution. (I am using storyboards but I am sure you can translate the code to work with nib files).
The first thing to do is create an instance of the storyboard:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
Then instantiate the tabbarcontroller:
UITabBarController *myTab = [storyboard instantiateViewControllerWithIdentifier:#"tabBar"];
Then instantiate the new view controller you want to add to the tabbar:
UIViewController *newVC = [storyboard instantiateViewControllerWithIdentifier:#"newView"];
This is the interesting part, you put all the view controller/tabs into an array and then add or remove views from that array. Then you set the view controllers of the tabbarcontroller to the modified array (I add one viewController and remove another).
NSMutableArray* controllers = [myTab.viewControllers mutableCopy];
[controllers insertObject:newVC atIndex:0];
[controllers removeObjectAtIndex:2];
[myTab setViewControllers:controllers];
Then you can just push your tab bar controller like this:
[self.navigationController pushViewController:myTab animated:YES];
Here I am using storyboards and ARC, you can modify it for nibs and release the array if you're not using ARC. This was fun to write! hope it helps! cheers!

How to push DetailView without NavigationController on UIViewController

I have a ViewBased App. I added a UITableView on one of the UIViewControllers. It shows the data and I implemented all the delegate methods etc. My problem is when I want to show the detailView it just doesn't happen. My code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController =[[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
NSLog(#"DidSelectRowAtIndexPath");
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
I see that I need a navigationController but I don't have one and I was unsucessful trying to add one programatically. I don't have one in my appDelegate either, so my question is do I need to add one to show the detail view? If yes, please give me a code sample how to do that.
If not, what other way is there?
I am new to iOS so I am a bit lost here.
Please help!
To add a navigation controller programmatically just for this detail view, you need to something like this:
UINavigationController * controller = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[[detailViewController] release];
[self presentModalViewController: controller animated: YES];
If you want to use pushViewController, you need to already have a navigation controller surrounding the view you're starting with.
You need to add the Navigation Controller FIRST, then your master table becomes the root view controller of the nav controller, then when you tap a row in the table, you push another view controller onto the nav stack.
How does your master table get into the app in the first place? If you're using a nib, it's super easy to just change out the view controller for a nav controller with the old view controller added as a child of the nav controller.
You can create one programmatically by working within your app delegate's application:didFinishLaunchingWithOptions: method like so:
UITableViewController *tableViewController = [[[WhateverYourSubclassVCIsCalled alloc] init] autorelease];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
window.rootViewController = navController;
[window makeKeyAndVisible];

Accessing a Top Navigation Controller from a Subview Navigation Controller

I have a my views and controllers set up like so.
A Tab/Bar controller
Within 1. is a root view controller
within 2. is a programmatically created navigation controller, that is displayed as a subview in the root view controller.
What I am trying to do is access the top tab bar/navigation controller so that i can push a view onto it.
I tried parentViewController but all it did was push the view onto the programmed nav controller.
any suggestions?
This is how i set up my root view controller:
-(void)viewDidAppear:(BOOL)animated{
NSLog(#"ROOT APPEARED");
[super viewDidAppear:animated];
WorklistViewController *worklistController = [[WorklistViewController alloc]initWithNibName:#"WorklistView" bundle:[NSBundle mainBundle]];
UINavigationController *worklistNavController = [[UINavigationController alloc] initWithRootViewController:worklistController];
worklistNavController.navigationBar.barStyle = UIBarStyleBlackOpaque;
worklistNavController.view.frame = watchlistView.frame;
[worklistNavController.topViewController viewDidLoad];
[worklistNavController.topViewController viewWillAppear:YES];
[self.view addSubview:worklistNavController.view];
GetAlertRequestViewController *alertsController = [[GetAlertRequestViewController alloc]initWithNibName:#"AlertsView" bundle:[NSBundle mainBundle]];
UINavigationController *alertsNavController = [[UINavigationController alloc] initWithRootViewController:alertsController];
alertsNavController.navigationBar.barStyle = UIBarStyleBlackOpaque;
alertsNavController.view.frame = alertsView.frame;
[alertsNavController.topViewController viewDidLoad];
[alertsNavController.topViewController viewWillAppear:YES];
[self.view addSubview:alertsNavController.view];
}
A nested ViewController (ie, inside a view controlled by a ViewController that's actually on the NavController stack) doesn't have direct access to the UINavigationController that its parent's view's controller is a stack member of. That's one MOUTHFUL of a sentence, but the sense of it is: you can't get there from here.
Instead you've got to get at the app's NavController via the App delegate.
YourAppDelegate *del = (YourAppDelegate *)[UIApplication sharedApplication].delegate;
[del.navigationController pushViewController:nextViewController animated:YES];
You're using your UIApplication's singleton (contains all sorts of good info about your app), which has a .delegate property pointing to the AppDelegate, and that contains a reference to the NavigationController.
This is how the "Navigation-based Application" Xcode template sets up NavController ownership, anyway. YMMV if you rolled your own--though if you did, you probably wouldn't need to ask this question.
You can use the follow instruccion:
[(UINavigationController *)self.view.window.rootViewController pushViewController:vc animated:YES];
It works for me :D
Have a look at UIViewController's navigationController and tabBarController properties. These will return the corresponding navigationController or tabBarController that the given UIViewController 'belongs' to.
So you can do something like:
[customController.navigationController pushViewController:newController animated:YES];
// Similarly for tabBarController ...