I am creating an app that uses a navigation controller.
In the the first view I have three different table views.
How can I make the tables open a new view in the navigation controller when one cell is selected?
Thanks
You implement tableView:didSelectRowAtIndexPath: as a delegate method on the view controller that shows the three table views, and in this method you initialize the new view controller you want to show and push it onto the screen by doing something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// TODO: Find out what view controller to push based on the tableView and the indexPath.
UIViewController *viewController = [[YourSpecialViewController alloc] initWithNibName:nil bundle:nil];
[[self navigationController] pushViewController:viewController animated:YES];
[viewController release];
}
Related
In iOS 8, view controllers can now call showDetailViewController:sender: to have the system determine the proper view controller to present the detail view controller.
In my app, I have a UISplitViewController, which contains two UINavigationControllers in its viewControllers array. The first UINavigationController contains my 'master' view, a subclass of UITableViewController. The second UINavigationController contains my 'detail' view.
Since I'm trying to make this work universally, I'm trying to use showDetailViewController:sender: to display the detail view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.itemVC.item = self.itemStore.items[indexPath.row];
[self showDetailViewController:self.itemVC sender:self];
}
This works fine with the Horizontal Compact trait (iPhone style), when self.splitViewController.collapsed == YES, but not when the trait is Regular (iPad, not collapsed). On the iPad, it replaces the detail UINavigationController with the bare detail view controller (instead of replacing that UINavigationController's viewControllers array).
To get around this, I'm tested for whether or not it's collapsed, and if it isn't, I'm wrapping the detail view controller in another UINavigationController before showing it:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.itemVC.item = self.itemStore.items[indexPath.row];
UIViewController *vcToShow;
// For whatever reason, when not collapsed, showDetailViewController replaces the detail view, doesn't push onto it.
if (self.splitViewController.collapsed) {
vcToShow = self.itemVC;
} else {
vcToShow = [[UINavigationController alloc] initWithRootViewController:self.itemVC];
}
[self showDetailViewController:vcToShow sender:self];
}
I suppose alternatively I could just configure self.itemVC and avoid calling showDetailViewController:sender: altogether when self.splitViewController.collapsed == NO:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.itemVC.item = self.itemStore.items[indexPath.row];
// For whatever reason, when not collapsed, showDetailViewController replaces the detail view, doesn't push onto it.
if (self.splitViewController.collapsed) {
[self showDetailViewController:vcToShow sender:self];
}
}
But, this feels like it's defeating the purpose of showDetailViewController:sender:, which is to loosen up the coupling between self and the rest of the view hierarchy.
Is there a better way to handle this?
In showDetailViewController:sender: depending on the collapse property you need to create the controller you want to show in the detail.
E.g. On the iPad in landscape mode it would already create the detail view controller from the storyboard but on the iPhone 5 where it is collapsed the view controller does not exist yet.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UINavigationController *detail;
ImageViewController *imageVC;
// on the iPhone (compact) the split view controller is collapsed
// therefore we need to create the navigation controller and its image view controllerfirst
if (self.splitViewController.collapsed) {
detail = [[UINavigationController alloc] init];
imageVC = [self.storyboard instantiateViewControllerWithIdentifier:#"ImageViewController"];
[detail setViewControllers:#[imageVC] animated: NO];
}
// if the split view controller shows the detail view already there is no need to create the controllers
else {
id vc = self.splitViewController.viewControllers[1];
if ([vc isKindOfClass:[UINavigationController class]]) {
detail = (UINavigationController *)vc;
imageVC = [detail.viewControllers firstObject];
}
}
[self prepareImageViewController:imageVC forPhoto:self.photos[indexPath.row]];
// ask the split view controller to show the detail view
// the controller knows on iPhone and iPad how to show the detail
[self.splitViewController showDetailViewController:detail sender:self];
}
I hope this solves your issue.
The way You doing it have a problem. If your rotate the device(change the mode from collapsed to allVisible) after you select, you will find the detail vc without a navigation controller.
If you call showDetailViewController:sender: in all cases and pass the view controller with a navigation controller it will work fine in both cases and also will fix the rotaion problem mentioned above.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.itemVC.item = self.itemStore.items[indexPath.row];
UIViewController *vcToShow= [[UINavigationController alloc] initWithRootViewController:self.itemVC];
[self showDetailViewController:vcToShow sender:self];
}
if (self.splitViewController.collapsed)
[self.splitViewController showDetailViewController:self.itemVC sender:self];
else
self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
So I created a new view controller which has the Custom class named DescriptionViewController.
And from my current view controller inside didSelectRowAtIndexPath I use this code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
DescriptionViewController *descriptionViewController = [[DescriptionViewController alloc] initWithNibName:#"DescriptionViewController" bundle:nil];
[self.navigationController pushViewController:descriptionViewController animated:YES];
}
But nothing happens when I click on a cell. Is there anything more I need to do ?
If you put in a breakpoint and it is stopping in the didSelectRowAtIndexPath, my guess is that your self.navigationController is nil.
If you are using storyboards, make sure your entry point is a UINavigationController and not a UIViewController.
If you loading this view controller though a modal transition, make sure you push on a navigation controller with this view controller as the root view instead.
Select your viewcontroller in the storyboard and on top go to editor->embed in->navigation controller then instead of initWithNibName try just init
I have a storyboard with tabbarcontroller. One of tab bar has a tableview and I want that when the user tap in a row from tableview open a detail view. The problem is when I open detail view tab bar and navigation bar hides... In the storyboard I create the detail view as a new view controller, then I create a new file and referred it to the class of detail view .
The code in didselectrowatindexpath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
detalleYouTube *dvController = [[detalleYouTube alloc] init];
[self.navigationController pushViewController:dvController animated:YES];
}
Thank you in advance!
This is kinda old but if someone needs to do this here's an easy approach:
You can use add a segue from the view in the tab bar to detalleYouTube, put an identifier to the segue and do this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"segueIdentifier" sender:tableView];
}
Another approach to this is not to use tableView:didSelectRowAtIndexPath but instead use prepareForSegue:sender
the way I did it was:
-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
DetailViewController *viewController = [segue destinationViewController];
CustomObject *custObject = [arrayOfObjects objectAtIndex:[self.tableView indexPathForSelectedRow].row];
viewController.objectNeeded = custObject;
}
This example is based on the idea that your detail view controller is connected to your table view controller.
I presume you have the 'Detail' view as part of the storyboard (not in a separate XIB), if so you will need to place a separate NavigationController at the start of the 'Detail' TabBarItem seque.
This page has a good tutorial on what I think your trying to achieve:
http://maybelost.com/2011/10/tutorial-storyboard-in-xcode-4-2-with-navigation-controller-and-tabbar-controller-part1/
Also check these links to a more in-depth Storyboard tutorial:
http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1
http://www.raywenderlich.com/5191/beginning-storyboards-in-ios-5-part-2
I am working on UISplitView Controller. I have used a SplitView controller template of Xcode. Actually i wanted to implement a scenraio in which when i click on table view cell it should add a New Root Controller with a table View into the Navigation Stack.
i did it using the following code
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NextViewController *nextView = [[NextViewController alloc] initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:nextView animated:YES];
[nextView release];
}
It works perfect and i have used the RootView Controller code into the NextViewController so that when we click on New Screen's cell it should update my Detail Screen. But unfortuantely it is not updating my Detail Screen.
What can be the reason ??
Please help friends..
Thanks
To updating your Detail Screen. you need to implement a delegate method of communication between Current RootView controller and Detailview controller.
Best Wishes,
I am trying to show detailed UItable view when clicking on row. I used
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherView" bundle:nil];
photoListViewController = [[PhotoListViewController alloc]initWithNibName:#"PhotoListViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:photoListViewController animated:YES];
[photoListViewController release];
// [self.navigationController pushViewController:anotherViewController];
// [anotherViewController release];
}
This PhotoListViewController is an empty UITableViewController. As I know UITableViewCOntroller has a navigation controller implemented and I don`t have to create navigation controller. But When I clicked on row it does not navigate to second view.AM I have to make some connection on nib file?I only created this PhotoListViewController in File->New->UIViewCOntroller and selected UITableView.
EDIT : SOLVED
I solved my problem.I should use UINAvigation object.I thought that UITable has it but there was no ))