Create UINavigationController in UITableViewController inside UITabBarController - uinavigationcontroller

I have an application with based of UITabBarController, and inside one of the tabs I have UITableViewController to display "products", till here everything is working perfectly.
Now I want when clicking one of the cells inside the UITableViewController to open a UINavigationController to display UIViewController with details of that product.
I think the application hierarchy should be like the following:
UITabBarController (BASE) Level-1
|
|___ UITableViewController (PRODUCTS) Level-2
|
|___ UINavigationController Level-3
|
|___ UIViewController (PRODUCT DETAILS) Level-4
How to achieve Level-3 and Level-4?
Thanks in advance :)

First You Will need to reset your hierarchy to something like this:
UITabBarController (BASE)
|
|___ UINavigationController
|
|___ UITableViewController (PRODUCTS)
|
|___ UIViewController (PRODUCT DETAILS)
You need to add a UINavigationController in the TabBarController, then you will use it to push the Product Detail.
to add a UINavigation on TabBarController:
UITabBarController *tabBarController = [[UITabBarController alloc] init];
UINavigationController *tableNavController_1 = [[[UINavigationController alloc] initWithRootViewController:YourProductViewController_1] autorelease];
UINavigationController *table2NavController_2 = [[[UINavigationController alloc] initWithRootViewController:YourProductViewController_2] autorelease];
tabBarController.viewControllers = [NSArray arrayWithObjects:tableNavController_1, table2NavController_2, nil];
//then add the controller to view like,
// this:
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
//or this:
[self.view addSubview:tabBarController.view];
I recommend you to create a new UITableViewController for each ProductViewController and then use the delegate method: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath for pushing the detail view:
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"Nib name" bundle:nil];
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES]
[detailViewController release];

Related

Segue to present contents of UITableViewController and NavigationController in iPad popover

I have a segue that works for iPhone code to present the contents of a tableViewController embedded in a Navigation controller.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UINavigationController *nc = (UINavigationController *)segue.destinationViewController;
tvc = (MyTableViewController *)[nc.viewControllers lastObject];
tvc.managedObjectContext = managedObjectContext;
}
tvc is a storyboard item, UITableViewController subclass, embedded in a navigationController. I am trying to find the easiest way to use the same setup on iPad, but present the contents in a popover, with a navigation controller, as opposed to presenting full screen as it's doing now. Else do I need to create a new viewController without using this setup?
I created a custom UIStoryboardPopoverSegue, with the following perform code:
- (void)perform
{
UITableViewController *src = (UITableViewController *) self.sourceViewController;
MyController *dst = (MyController *) self.destinationViewController;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:dst];
UITableViewCell *cell = [src.tableView cellForRowAtIndexPath:[src.tableView indexPathForSelectedRow]];
UIPopoverController *pop = [[UIPopoverController alloc] initWithContentViewController:navigationController];
dst.popoverController = pop;
CGSize size = CGSizeMake(475, src.view.frame.size.height);
pop.popoverContentSize = size;
[pop presentPopoverFromRect:cell.frame
inView:src.tableView
permittedArrowDirections:UIPopoverArrowDirectionUp | UIPopoverArrowDirectionDown
animated:YES];
}
The downside of this is that it requires a seque that is custom to destination view controller. The upside is an easy to implement and support, well functioning popover segue.

Can't access detailViewController from UINavigationController

I'm trying to get a reference to my detailViewController in application didFinishLaunchingWithOptions: method. But here I am faced with a problem.
I have next Views structure is storyBoard (for iPad):
UISplitViewController --> UINavigationController --> UITableViewController --> detailViewController
I created segue with "push" style between UITableViewControllerCell and detailViewController
Screenshot: http://picturepush.com/public/13071076
I'm trying to get a reference to detailViewController in this way:
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
DetailViewController *detailViewController = [navigationController.viewControllers lastObject];
But in result I got reference to my UITableViewController, instead of acceptable
DetailViewController. The navigationController.viewControllers count is 1 but there should be 2 (I think so).
I hope for your help.
Since you created a segue with push style, the detailViewController will only be loaded after you tap on a table view cell. It will not be loaded on the app didFinishLaunchingWithOptions method.
I would suggest you try to make the detailViewController as a property in your table view controller.
#property (nonatomic, strong) UIViewController *detailViewController;
Then in your app didFinishLaunchingWithOptions method, you can access the property:
UITableViewController *tableViewController = [navigationController.viewControllers lastObject];
DetailViewController *detailViewController = tableViewController.detailViewController;
But you will need to avoid using perform segue function and push the detail view controller whenever it is needed with the usual pushViewController method.
[self.navigationController pushViewController:self.detailViewController animated:YES];

Split View Controller with a sliding master view , swipe gesture

I am working on an iPad application, It has the split view and i want to allow the master view to be displayed/hidden with a swipe gesture similar to the way the mail app from Apple now works. I have created the split view. Could anyone please tell me how to hide/show the master view. I also want to place a button in the detail view so if user clicks that button if master view is open it will hide it, if its already hidden by pressing the same button it will show the master view.
Help appreciated
Thanks
MasterViewController *masterViewController = [[MasterViewController alloc] init];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
DetailViewController *detailViewController = [[DetailViewController alloc] init];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.viewControllers = [[NSArray alloc] initWithObjects:masterNavigationController,detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
[self.window addSubview:self.splitViewController.view];
I think https://github.com/mattgemmell/MGSplitViewController will help you.
This article could helpful to you.
http://useyourloaf.com/blog/2011/11/16/mail-app-style-split-view-controller-with-a-sliding-master-v.html

Adding BarButtonItem to a Modal Navigation View Controller

I am presenting a modal navigation bar controller initialized with a root controller (which is a UITableViewController). When I, initialize the UINavigationBarController to present it modally, I am also adding a "Submit" button as a right bar button item. Everything is working fine (loading with root view and Modal presentation) However, the right button is not showing.
Posting the code below -
-(IBAction) presentAddLeaveRequestModally {
AddLeaveRequestViewController *leaveRequestViewController = [[AddLeaveRequestViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:leaveRequestViewController];
UIBarButtonItem *submitButton = [[UIBarButtonItem alloc] initWithTitle:#"Submit"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(submitLeaveRequest)];
navController.navigationItem.rightBarButtonItem = submitButton;
[self.homeTabBarController presentModalViewController:navController animated:YES];
}
Any ideas if I am missing something obvious?
Got the problem ... was adding rightBarButtonItem to navController's navigationItem ... I should be adding it to rootViewController's navigationItem in viewDidLoad.
UIBarButtonItem *submitButton = [[UIBarButtonItem alloc] initWithTitle:#"Submit"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(submitLeaveRequest)];
self.navigationItem.rightBarButtonItem = submitButton;

uinavigationController's toolbar with custom items

I am trying to use the NavigationController's toolbar in my app. This toolbar's toolbarItems are suppose to change depending on which view controller is presented. this is very basic.
What I am trying to do is to add custom buttons to the toolbar using the UIBarButtonItem's "initWithCustomView:" method. However, the button won't show up on the toolbar. But if I create the UIBarButtonItem using the "initWithTitle:" or "initWithBarButtonSystemItem:" method, the button show up. For example, look at the code below:
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemBookmarks target:self action:nil];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:#"edit" style:UIBarButtonItemStylePlain target:self action:nil];
NSArray *array = [[NSArray alloc] initWithObjects:item1, item2, nil];
[self setToolbarItems:array];
If this is done, buttons show up on the toolbar. But, if I were to do the following:
UIButton* replyBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[replyBtn setImage:[UIImage imageNamed:#"Reply_Message.png"] forState:UIControlStateNormal];
[replyBtn addTarget:self action:#selector(replyButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
replyBtn.frame = CGRectMake(10, 0, 40, 40);
UIBarButtonItem *replyButton = [[UIBarButtonItem alloc] initWithCustomView:replyBtn];
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemBookmarks target:self action:nil];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:#"edit" style:UIBarButtonItemStylePlain target:self action:nil];
NSArray *array = [[NSArray alloc] initWithObjects:item1, replyButton, item2, nil];
[self setToolbarItems:array];
In this code, only the item1 and item2 are displayed on the toolbar. replyButton is not shown on the toolbar. There is blank space at the place where the button is suppose to be at.
If this same code used on a regular toolbar that I create instead of NavigationController's toolbar, the button shows up. I am trying to just use one toolbar throughout the app to have the same feel that Apple's Mail application does. The reason that I need to use the "initWithCustomView:" method is because one of the icons is colored and this is the only way it shows up colored on a normal toolbar. Now, I have looked through apple documentation and there isn't any mention of why the "initWithCustomView:" method couldn't be called (or maybe I couldn't find it).
Could please somebody shine some light on this topic to help me point in the right direction. thanks in advance guys.
I can't see the difference from what you tried, but it eventually worked for me, with that code:
//////////////////////////////////////////////////////////////////////////////////////////////
/////>>>> Adding buttons for browsing in the toolbar of the popover's navigation controller///
//////////////////////////////////////////////////////////////////////////////////////////////
//>>>>Create a goBack button
goBack = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *goBackImage = [UIImage imageNamed:#"back1.png"];
[goBack setImage:goBackImage forState:UIControlStateNormal];
[goBack addTarget:self action:#selector(goBackClicked:) forControlEvents:UIControlEventTouchUpInside];
goBack.frame = CGRectMake(0,0,goBackImage.size.width,goBackImage.size.height);
//Create a Bar button to hold this button
UIBarButtonItem *goBackBarButton = [[[UIBarButtonItem alloc] initWithCustomView:goBack] autorelease];
UIBarButtonItem *flex1 = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease];
UIBarButtonItem *addButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:nil action:nil] autorelease];
NSArray *arrayOfButtons = [[[NSArray alloc] initWithObjects:goBackBarButton, flex1, addButton, nil] autorelease];
[self setToolbarItems:arrayOfButtons];
Note few differences from yours (maybe that's where the catch? I'm not sure):
1. my buttons are not allocated locally in the method, but in the class (you know, the property, synthesize, etc)
2. yours
[replyBtn setImage:[UIImage imageNamed:#"Reply_Message.png"] forState:UIControlStateNormal];
where mine looks a bit different
[goBack setImage:goBackImage forState:UIControlStateNormal];
Try these tiny changes, maybe it will work :)
I was having the same problem. It turns out that the toolbar for the UINavigationController resets it's items every time a new view gets pushed on the stack. I was trying to set the toolbar items in the applicationDidFinish function, and it was not working. It worked once I set the toolbar itms in the - (void) viewDidAppear function of the viewController that was being pushed onto the navigation stack.
So, it seems like if you want the navigation controller to keep the same toolbar items throughout the application, you have to set the toolbar items in each view that you push onto the navigation controller after the view appears.
I hope that helps!
I'd wager a guess that the item isn't showing up because its view doesn't have anything in it. Are you sure there's an image called Reply_Message.png in your project? [UIImage imageNamed:#"Reply_Message.png"] might be nil.
You can use one toolbar throughout your app without using the navigation controllers toolbar. Since your code works with a non-navigationController toolbar, this might be the easiest way to accomplish what you want. In your app delegate, try adding a toolbar to window, like this. This way it is persistent throughout the app. Make sure you consider a scheme that will let you access the toolbar to add/remove buttons, or hide/show it from different view controllers.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/////// frame sizes ////////
// compensate for the status bar
int statusBarHeight = 20;
// toolbar
int toolbarWidth = window.frame.size.width;
int toolbarHeight = 30; // I think standard size is 30
int toolbarxOffset = 0;
int toolbaryOffset = window.frame.size.height - tHeight;
CGRect toolbarFrame = CGRectMake(toolbarxOffset,
toolbaryOffset,
toolbarWidth,
toolbarHeight);
/////// toolbar //////////////////////
self.myPersistentToolbar = [[UIToolbar alloc] initWithFrame:toolbarFrame];
[window addSubview:self.myPersistentToolbar];
}

Resources