2
votes

I am working on an app that displays a list of places. There is a NavigationController, and in the navigation bar I have some UIBarButtonItem (left and right), and the center section is a custom view with a label and two UIButton's.

ToolBar

The map button performs a segue to a MapViewController that displays the points on a map. What I want to achieve is that the navigation bar of the map ViewController also displays the same custom UIView (showing the arrow buttons and the Day Label), but I don't know how to achieve this. I've tried to copy the view on prepareForSegue:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if ([segue.identifier isEqualToString:@"FlipFromListToMap"]) {
        if ([segue.destinationViewController isKindOfClass:[DisplayTourMapViewController class]]){
            DisplayTourMapViewController *cityListController = segue.destinationViewController;
cityListController.navigationItem.titleView = self.navigationItem.titleView;
        }
    }
}

But this is not working. Furthermore, when a go back the navigation view from the original table view is gone:

Gone

I'd like to know whether my approach is wrong or not. Can I keep the navigationcontroller views between segues? Is it ok that I am using navigationcontroller and segue's? Or should I just have two views inside the controller and swap them programatically? The model for the two views is the same, it only changes the way I present the information (map or list).

Thanks in advance.

3

3 Answers

1
votes

The reason that title view doesn't appear on first navigation controller when you come back to it is that you have changed its superview. Each view can only have one superview, and you moved that one to next view controller's view.

But I don't know why it doesn't appear at all on second view controller. I just made a sample app with exact same code as yours and the next view controller does display first one's title view. When it gets back however, there is no title view on first one. I tried to work around this by storing the title view inside a property on first controller and setting it again in viewWill/DidAppear: if it's not nil, but it shows title view during animation and then removes it.

All of this doesn't sound like intended behavior, so I'm gonna do some more testing and report a bug (or come back with a better answer). I suggest you do the same.

0
votes

I had the same problem: the pushes working correctly with the titleView item, but the pops letting it disappear after the navigation animation finished. I tried just about every combination, but this is what finally worked:

1) In the navigation controller's delegate (which I set to be itself), I inserted:

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    viewController.navigationItem.titleView = self.myCustomView;
}

2) Then in each individual view controller (I had 3), I inserted:

- (void)viewWillDisappear:(BOOL)animated
{
    self.navigationItem.titleView = nil;
}

It's really important to use these particular callback methods. It didn't work at all when I used willShowViewController: in the first and/or viewDidDisappear: in the second.

The problem with trying to do it in a prepareForSegue: is that it only works in the push direction. You do have access to both controllers though, in the destinationViewController and sourceViewController fields of the segue itself. But to make it work in the other direction, you'd have to put the same code in the unwind segue. I think my solution is probably the simplest (particularly since you're wanting to do it for all the view controllers that your nav controller manages).

-1
votes

Ok I finally figured it out. I think the best way to implement this kind of behavior is not using a segue between viewcontrollers. Since both views are different ways to present the same data, I implemented a controller that has the two views (list and map), and then use a button to perform an action that swaps views, as comented in apple developer library:

- (IBAction)toggleMainViews:(id)sender {
    [UIView transitionFromView:(displayingPrimary ? primaryView : secondaryView)
        toView:(displayingPrimary ? secondaryView : primaryView)
        duration:1.0
        options:(displayingPrimary ? UIViewAnimationOptionTransitionFlipFromRight :
                    UIViewAnimationOptionTransitionFlipFromLeft)
        completion:^(BOOL finished) {
            if (finished) {
                displayingPrimary = !displayingPrimary;
            }
    }];
}

Animations Apple Developer Library

Using this approach I don't change viewControllers, so the navigation bar stays the same and I can keep the buttons just as needed.