Paging scroll view with child view controllers - ios

What is the best practice for implementing a horizontal scroll view with paging, with one view controller per page?
Is the PageControl example still the best way to implement this now that iOS5 has API for view controller containers/containment?

I know this question is a little old, but as of iOS 6, UIPageViewController has a new transition style property called UIPageViewControllerTransitionStyleScroll which lets you use the page controller for a use case like yours, with simple scrolling between pages instead of the iBooks-style page curl transitions.
You should also watch the 2012 WWDC video number 223 - Enhancing User Experience with Scroll Views where they basically transition an old app that uses the method you describe to the new UIPageViewController with scroll style transition.

My answer would be that it depends on your goal. If you want to make an app as efficiently as possible, I would just use the way it is done in the sample code. I have used it before, and I would do it again.
On the other hand, if your goal is to learn about view controller containment, how it works and how to use it, this might be a good case to try it out. If you go that way, don't forget to check out the WWDC video "Implementing UIViewController Containment" (https://developer.apple.com/videos/wwdc/2011/).

Appears best practice as of iOS5 is to remain using the same method as the PageControl example. That is one controller class (note not a view controller). With child view controllers for each page.
As of now there is no documented better way to implement a paging scroll view using view controller containment methods included in iOS5.

I would suggest a UIPageViewController instead.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html

I think UIPageViewController can go horizontally:
- (id)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation options:(NSDictionary *)options
And
enum {
UIPageViewControllerNavigationOrientationHorizontal = 0,
UIPageViewControllerNavigationOrientationVertical = 1
};
typedef NSInteger UIPageViewControllerNavigationOrientation;
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html

If you add your View Controllers views (myViewControllerOne.view) to the UIScrollView - and then appropriately frame them to appear horizontally - when the user interacts with that view inside of the scroll view methods in the View Controller will be called.
By this I mean if you have MyViewControllerOne.view as a sub view inside of your scroll view, when you scroll to that 'page' of the scroll view and press the button the attached method (IBAction etc) in MyViewControllerOne will be called.
This should give you all the functionality you need such as adding UI Elements, tables, another scroll view, etc.. These elements will be controlled from their originating View Controller.
Hope this helps!

Related

Xcode Swift how to place UIViewController beneath parent UIView Controller

I would like to make similar effect that Facebook app has. So I would like to create navigation slide-out effect.
But when I place UIViewController with menu beneath parent UIViewController with content and then I move parent view aside my menu doesnt show up. Everything I can see is black screen. But menu frame is in the right position.
Any sugestion what should I do?
Content view will be separate UIViewControllers.
I was in the same situation than you and finally I used a custom class which is inspired on FaceBook and Wunderlist apps and is really simple to add into the project:
https://github.com/John-Lluch/SWRevealViewController
The child view controller is always above parent view controller's view.
I think the old and the new view controllers should be siblings and use a parent view controller to add them both.
In fact, the child controllers of native UINavigationController are siblings rather than child-parent relationship.
I would urge you not to do this on your own but to use one of the many libraries out there that have been heavily tested by many contributors. One of the good ones is MMDrawerController but there are many others. Take a look at cococontrols for many more examples.
I've previously implemented a similar mechanic to this using custom transitions, which were introduced in iOS7. For example: could present the menu modally, but using a custom transition have it appear from the left and only take up a proportion of the screen.
Using custom interactive transitions will also allow you to use a pan gesture recogniser to drag your main view controller back on top of your menu - like in the Facebook app.
Here's a good tutorial on Custom Transitions: http://www.thinkandbuild.it/ios7-custom-transitions/

Custom UICollectionView paging transition

I know that I can do custom transitions between view controllers but I'm not sure that applies here. I have a collection view with paging enabled. When swiping/paging I want to do a custom transition instead of just sliding across. Is this possible and how would I get started?
After some research this doesn't seem possible. The only solution would be displaying a collection view in a UIViewController and using a custom view controller animation on pan to create a new instance of that view controller with the collection view. Clearly not ideal but the only thing I could come up with.

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
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.
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.
A couple of thoughts:
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.
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.
I definitely wouldn't recommend using a UINavigationController, though, because it will keep all of the previous pages in memory.
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!
As far as I see, there are 2 good options:
Using a root UINavigationController and push/pop child
ViewControllers depending on the direction of the swipe gesture
(recognized by UISwipeGestureRecognizer, just as you said).
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
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.

iPhone tableview drop-down menu

I have a view controller with a table view in it and several buttons. I would like to add an additional tableview on top of the view like this (or at least what it would look like if anybody wanted to be my friend :-)):
I don't want to just add this as a subview (like here or here)enter link description here since I don't want to check which table view is being used in my tableview delegate and datasource methods. I would rather use a separate view controller.
I don't want to use a picker because I need to display a bit of info with the items in the list.
I have no problem creating the view with the corresponding controller, but how do I add it on top of the current view, just hiding portions of it?
Thanks!
Apple has a sample code of TableView which deals with this issue. https://developer.apple.com/library/ios/#samplecode/TableViewUpdates/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40010139
Above URL is the link to download the sample code from Apple developer library.
Hope it helps.
This might be overly simplistic for your application, but I have found it to be effective when I have had to do something similar.
You can add this 'drop down menu' view controller's view to the main UIWindow of the entire application. You can add a UIGestureRecognizer on the window as well. If the tap is outside of the view, make it fade away and remove it from the view hierarchy.
Initially I simply added logic in my tableview datasource and delegate methods to destingwish between the two tableviews (as suggested by Scott Bossak above. But I have since switched to building my two views in storyboard and adding their view controllers as usual. However, to present the second table view I instanciate it like so:
SecondTableViewContriller *secondTVC = [self.storyboard instanciateViewControllerWithIdentifier:#"secondTVC"];
then add it as a child view controller:
[self addChildViewController: secondVC];
[secondVC didMoveToParentViewController:self];
I then implemented a protocol to pass the information back to the parent view controller once a row has been selected.

UIViewControllers in UIScrollView?

I have a design question. I have a scroll view that I want to use as a means of navigation. I.e. the user can slide between screens. At present, I am creating view controllers and putting their views directly on the scroll view:
aViewController.view.frame=CGRectMake(0,0,320,200);
[self.myScrollView addSubview:[aViewController view]]
Etc, for all 3 view controllers.
I know this isn't best practice. But I can't think of any other way of doing it. Ideally I would like to get the same behaviour as a navigation controller except the fact that I'll be using a scroll view. Any help would be greatly appreciated.
You have to be aware that this breaks certain UIViewController behaviors because these child view controllers do not get informed about interface rotation events and their viewWill/Did(Dis)Appear: methods will not work.
The alternative (until iOS 4.x at least) is to not use UIViewController subclasses for these subviews. You could easily create your own custom controller class (derived from NSObject) to manage a child view.
It's debatable whether that approach makes it easier overall, though.
I'm guessing what you're trying to achieve is something similar to this app?
http://itunes.apple.com/us/app/fanhattan-for-ipad/id436928538?mt=8
This app works in the same manner, using a scroll view for navigation. You can analyze that app, you'd get some ideas from it, i'm sure.

Resources