views:

321

answers:

1

Given an iPhone app with a UITableViewController pushed onto a UINavigationController, I would like to add a right bar button item to toggle between the table view and an "alternate" view of the same data. Let's also say that this other view uses the same data but is not a UITableView.

Now, I know variations on this question already exist on Stack Overflow. However, in this case, that alternate view would not be pushed onto the UINavigationController. It would be visually akin to flipping the current UIViewController's table view over and revealing the other view, then being able to flip back. In other words, it's intended to take up a single spot in the UINavigationController hierarchy.

Moreover, whatever selection you ultimately make from within either view will push a common UIViewController onto the UINavigationController stack.

Still more info: We don't want to use a separate UINavigationController just to handle this pair of views, and we don't want to split these apart via a UITabBarController either. Visually and contextually, the UX is meant to show two sides of the same coin. It's just that those two sides happen to involve their own View Controllers in normal practice.

Now … it turns out I have already gone and quickly set this up to see how it might work! However, upon stepping back to examine it, I get the distinct impression that I went about it in a rather non-MVC way, which of course concerns me a bit.

Here's what I did at a high level.

Right now, I have a UIViewController (not a UITableViewController) that handles all commonalities between the two views, such as fetching the raw data. I also have two NIBs, one for each view, and two UIView objects to go along with them. (One of them is a UITableView, which is a kind of UIView.)

I switch between the views using animation (easy enough). Also, in an effort to keep things encapsulated, the now-split-apart UITableView (not the UIViewController!) acts as its own delegate and data source, fetching data from the VC. The VC is set up as a weak, non-retained object in the table view. In parallel, the alternate view gets at the raw data from the VC in the exact same way.

So, there are a few things that smell funny here. The weak linking from child to parent, while polite, seems like it might be wrong. Making a UITableView the table's data source and delegate also seems odd to me, thinking that a view controller is where you want to put that per Apple's MVC diagrams. As it stands now, it would appear as if the view knows about the model, which isn't good. Loading up both views in advance also seems odd, because lazy loading is no longer in effect. Losing the benefits of a UITableViewController (like auto-scrolling to cells with text fields) is also a bit frustrating, and I'd rather not reinvent the wheel to work around that as well.

Given all of the above, and given we want that "flip effect" in the context of a single spot on a single UINavigationController, and given that both views are two sides of the same coin, is there a better, more obvious way to design this that I'm just happening to miss completely? Clues appreciated!

A: 

My approach would be as follows, but I haven't tested this to try it out. UINavigationController has a property, viewControllers, that returns an array of the view controllers currently on the navigation controller's stack. There is also a method, setViewControllers:animated, that allows you to set all of a navigation controller's view controllers at once. When the user wants to switch from the table view to the alternate view, do the following: 1. Get the array of view controllers on the nav controller's stack. 2. Replace the final array element with the tableView or alternate non-table view controller. 2. Use the setViewControllers:animated to put the stack back in the nav controller with the desired view controller on top.

The flipping animation, if you want it, would then have to be handled in the view controller's viewDidLoad or viewDidAppear method.

Drew C
Hmmm, an intriguing option - thanks! I gather I'll need to change over to separate VCs in order to pull this off, but it sounds plausible at first glance.
Joe D'Andrea