bcattle
bcattle

Reputation: 12819

App structure: UIView vs. UIViewController in a paging interface

There are some great answers relating to when to use a UIViewContoller vs. a UIView. For example here and here.

The general gist is that a UIVIewController should be used to control a full screen of data, because

  1. It is designed to handle rotation. Only one UIViewController should be on the screen at once because only the newest will be notified that the rotation occurred.

  2. To stay true to the MVC paradigm, your business logic should live in a UIViewController, while only display and interaction logic should live in a UIView. Presumably business logic relates to what's on the entire screen.

My question is, given this, how do I structure an app with left-right paging between several top-level views?

I want to create an interface with several UITableViews holding a list of recipes. The user swipes left and right to navigate between lists. There is a common menu on the bottom that stays fixed no matter what.

My initial thought is to use one UIVIewController for the UIScrollView, then add subviews from there.

However I'd really like each list to have its own UIViewController, so it can handle its own rotation, and hold business logic like its own REST methods. It would seem to be a pain to have the top-level UIViewController handle the rotation of a child subview, and it would seem to be a violation of MVC to put the logic anywhere else.

Is there a way to structure an app so that multiple UIViewControllers live inside a UIScrollView, or would it appropriate to use a series of top-level UIViewControllers and UISwipeGestureRecognizer to simulate the paging effect of the UIScrollView?

Thanks.

Upvotes: 3

Views: 1342

Answers (4)

Rob
Rob

Reputation: 437422

A couple of thoughts:

  1. If targeting iOS 5 and higher, I'd suggest using a UIPageViewController which is designed for precisely this UI (swiping back and forth between UIViewController instances). You would then have a separate UIViewController for each recipe. In iOS 5, you only have UIPageViewControllerTransitionStylePageCurl transition style, but in iOS 6, you also have UIPageViewControllerTransitionStyleScroll.

    For more information, see the Page View Controller section of the View Controller Catalog for iOS.

  2. This is much simpler than writing your own scroll view based solution. If you "roll your own" with a UIScrollView, you'll want to remove instances that have scrolled off screen (by registering as the scroll view's delegate and responding to scrollViewDidScroll) so you don't use up memory unnecessarily.

    If you do add child view controllers to your scroll view, don't forget to call the appropriate custom container calls. Specifically, as you add view controllers to your scroll view, make sure you call the following (assuming controller is the child controller and self is the main view controller):

    [self addChildViewController:controller];
    [self.scrollView addSubview:controller.view];
    [controller didMoveToParentViewController:self];
    

    And as you respond to scrollViewDidScroll to remove view controllers that are no longer visible, do the appropriate removal calls, e.g.:

    [controller willMoveToParentViewController:nil];
    [controller.view removeFromSuperview];
    [self removeChildViewController:controller];
    

    For information about why it's important to call these custom container calls, see WWDC 2011 video Implementing UIViewController Containment.

  3. I definitely wouldn't recommend using a UINavigationController, though, because it will keep all of the previous pages in memory.

Upvotes: 2

tarmes
tarmes

Reputation: 15442

Firstly, you should be aware that since iOS 5 it's been possible to include child view controllers inside your main view controller.

https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html

So it seems to me that a good options would be to have a paged UIScrollView as your main controller, and then to put instances of your child controller onto each page.

Since that could all be a little memory intensive, you should really only have three instances at any one time (one being displayed, and one one either side so that they're ready if the user starts to scroll). The Apple demo project shows you how to configure a scroll view like that:

https://developer.apple.com/library/ios/samplecode/PageControl/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007795

Hope that helps.

Upvotes: 1

tamas.levi
tamas.levi

Reputation: 11

As far as I see, there are 2 good options:

  1. Using a root UINavigationController and push/pop child ViewControllers depending on the direction of the swipe gesture (recognized by UISwipeGestureRecognizer, just as you said).

  2. Using a root UIViewController with a UIScrollView and adding the child viewcontroller views as subviews of the scrollview. To handle orientation changes, you could pass the orientation-change UIViewController methods (willRotateToInterfaceOrientation, didRotateFromInterfaceOrientation) to the child controllers, so they can handle them.

I hope I helped

Upvotes: 1

LuisCien
LuisCien

Reputation: 6432

I believe for the requirements you're talking about you could use a UINavigationController. It will give you the "left-right" paging that you want and you can use a UIViewController for each of your recipes.

Also, I think you want to use a UIScrollView because it lets you perform a "swipe" gesture. If that's the case you could also add a UISwipeGestureRecognizer to your view controllers and every time the gesture is recognized call pushViewController:animated: and popViewControllerAnimated: to perform navigation between your recipes.

This is just and idea.

Hope this helps!

Upvotes: 1

Related Questions