views:

1626

answers:

5

I have a UINavigationController and I have seperate UIViews that I switch between using a UISegmentControl. On switching the views, I add the view as a subview to my navigation controller's view:

[self.view addSubview:segmentTab1.view];

and

[self.view addSubview:segmentTab2.view];

Then, in the subViews, each has a UITableView, but my issue is, that I am unable to push a new viewController into view in the didSelectRowAtIndexPath method.

The method is called correctly and by setting breakpoints, I can see the method for pushing the view gets called as well, but nothing happens. This is my code for pushing it:

[self.navigationController pushViewController:detailsViewController animated:YES];

I also tried

[super.navigationController pushViewController:detailsViewController animated:YES];

What am I doing wrong - or is is just not possible to do it with a subview?

+3  A: 

When you call -pushViewController, which view controller is self? If you are calling that from within one of your tab subviews, self likely doesn't have a reference to the navigation controller from the top level view that you added it to. You can verify this by getting the memory address of the navigation controller from within the top level view and comparing it to what you have in the subview. Obviously if it's nil or doesn't match, then that's your problem.

You only get a navigation controller "for free" when it's been added to the navigation stack itself with -pushViewController which your subviews haven't been added that way.

Matt Long
Exactly -- the call to pushViewController must come from a view that has itself been pushed onto the navigation controller. It does not necessarily have to be the last one pushed, but it DOES have to be on the navigation controllers stack.
Amagrammer
Clarification: "must come from a view CONTROLLER" -- not a view.
Amagrammer
Thanks, Matt. And 'Amagrammer'. I have tabs, with NavigationControllers in each, which have a nib and a class attached to their views. I am going to set it up, so each tab has a view controller, and in each of the viewcontroller, I add a UINavigationController, which switches out it's views based on the segmentedControl and hopefully I can push in subviews, when I get there :)
Canada Dev
Basically. The App Store app on the iPhone is an example of what I want to achieve. TabBar, each with a UINavigationController that have segmentedController (some of them do at least) and the rows can be pushed.
Canada Dev
I agree, when you add a subview to an existing view, it won't include a reference to the navigation controller and your pushViewController:animated: calls will be sent to nil and ignored. Interestingly, the App Store application (and several others) look like they use segmented controls to filter table data in a single nib, rather than as a selection between different nibs (essentially a tab view).
crafterm
A: 

It is not entirely clear to me what your view hierarchy is, but in general if your navigation controllers view is not the first subview of a window or an element of one of Apple's collection views (either another navigation view controller's content view or a tab controller's content view) it won't work correctly.

Louis Gerbarg
A: 

Instead of

[self.view addSubview:segmentTab1.view];

and

[self.view addSubview:segmentTab2.view];

you may use

[self pushViewController: segmentTab1 animated: NO];

and

[self pushViewController: segmentTab2 animated: NO];

to add your viewControllers to the navigation hierarchy, and make [super.navigationController pushViewController:detailsViewController animated:YES]; work.

luvieere
Not sure if this will work, but if you switch out views in the segmentController, and you use a TabBar, tapping the tabBarItem for that view will push back the view. Doesn't look so good :(
Canada Dev
I'm not sure I understand this behavior correctly. Perhaps you should look at *visibleViewController* property of the navigationController, and if it corresponds to the view you're trying to push, don't push it anymore.
luvieere
A: 

One possibility, if you are not averse to singletons, is to make your product's UINavigationController object be a singleton, accessible from (for example) your application delegate.

You would invoke it thus:

[[((MyApplicationDelegate*)[UIApplication delegate]) navController] 
                pushViewController: viewControllerToPush animated: YES];

where within MyApplicationDelegate, navController returns the singleton object.

Amagrammer
A: 

Hey everyone. I am having the exact same issue. I followed instructions from this video: http://www.youtube.com/watch?v=LBnPfAtswgw&feature=player%5Fembedded#. I changed some things around to make it work with what I am trying to accomplish but the underlying logic I left the same. She is working with SDK 2.* and I am using 3.*. I assume this has something to do with it. Can anyone help me out? This is what my didSelectRowAtIndexPath looks like :

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
    NSInteger row = [indexPath row];
    if(self.detailViewController == nil) {
     LogEntryDetailViewController *logEntryDetail = [[LogEntryDetailViewController alloc]
                 initWithNibName:@"LogEntryDetailView" bundle:[NSBundle mainBundle]];
     self.detailViewController = logEntryDetail;
     [logEntryDetail release];
    }

    detailViewController.title = [NSString stringWithFormat:@"%@", [logEntriesArray objectAtIndex:row]];

    ProgNameAppDelegate *delegate = (ProgNameAppDelegate *)[[UIApplication sharedApplication] delegate];
    [delegate.logViewNavController pushViewController:self.detailViewController animated:YES];
}

I am going nuts here. If I need to post this somewhere else I will be happy to do so. Thanks in advance!

Trent