14

I am trying to set up a UIScrollView so that I can swipe between my 3 view controllers. This is my code in AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.;

UIScrollView *sv = [[UIScrollView alloc] init];

BarsViewController *bvc = [[BarsViewController alloc] init]; // Create BarsViewController
StopwatchViewController *svc = [[StopwatchViewController alloc] init]; // Create StopwatchViewController
TimerViewController *tvc = [[TimerViewController alloc] init]; // Create TimerViewController

[sv addSubview:bvc.view];
[sv addSubview:svc.view];
[sv addSubview:tvc.view];

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade]; // Hide status bar

self.window.rootViewController = sv;
[self.window makeKeyAndVisible];
return YES;
}

It gives an error on this line:

self.window.rootViewController = sv;

saying, "Incompatible pointer types assigning to 'UIViewController *' from UIScrollView *'".

However, there is no such thing as a UIScrollViewController, so I don't know what to do.

Basically, I just want the whole screen to be a scroll view which allows me to swipe between my 3 view controllers. How would I go about doing that?

Neil Galiaskarov
  • 5,015
  • 2
  • 27
  • 46
user2397282
  • 3,798
  • 15
  • 48
  • 94
  • Wenderlich has a similar tutorial made on UIImageView. Try changing UIImageView and using UIViewControllers instead. http://www.raywenderlich.com/10518/ (under Paging with UIScrollView) – Anil Nov 06 '13 at 19:42
  • 1
    @Anil, Apparently, that is not that case, because you should think about parent-child view controller hierarchy. – Neil Galiaskarov Nov 06 '13 at 19:51

4 Answers4

39

UPD: June, 2015 Swift

The concept remains the same, which is described below in Objective-C section. There is a little change in syntax. To add childviewcontroller use following snippet:

let aViewController = storyboard.instantiateViewControllerWithIdentifier("A") as! AViewController;

addChildViewController(aViewController);
scrollView!.addSubview(aViewController.view)
aViewController.didMoveToParentViewController(self)

Check my Swift Github Sample Code

Objective-C

Create your own custom container view controller (I will call it combinedViewController), which will hold your three controllers in scroll view. Inherit like you always do UIViewController, then use addChildViewController public API in your new combinedViewController -viewDidLoad: like this:

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

Here’s what the code does:

  • It calls the container’s addChildViewController: method to add the child.
  • It accesses the child’s view property to retrieve the view and adds it to its own view hierarchy. The container sets the child’s size and position before adding the view; containers always choose where the child’s content appears.
  • It explicitly calls the child’s didMoveToParentViewController: method to signal that the operation is complete.

Do this operation with each of your viewControllers. Afterwards, set your combinedViewController as a rootViewController.

if you need further explanation, feel free to ask.

Reference: Design custom container view controller

Here you are my Objective-C Github sample code

UPD: Thanks @Oliver Atkinson for clarifying that addChildViewController: method also calls the child’s willMoveToParentViewController: method automatically.

Results:

enter image description here

Neil Galiaskarov
  • 5,015
  • 2
  • 27
  • 46
  • Thank you very much for this answer, but I'm a little lost; I'm really quite new to Objective-C and I'm still learning. I created a new viewcontroller and imported the header files of my 3 view controllers. I tried copying your code, and replacing aViewController with BarsViewController, but it said, "No known class method for selector 'willMovetoViewController:'", along with other different errors on all the lines. Is that what I'm supposed to do? Sorry about this. – user2397282 Nov 06 '13 at 19:43
  • sorry my mistake, you should write `-willMoveToParentViewController:` – Neil Galiaskarov Nov 06 '13 at 19:46
  • I don't that works either- it gives the same error, "No known class method for selector 'willMovetoParentViewController:'". Am I not doing this right? – user2397282 Nov 06 '13 at 19:51
  • Firstly, check the spelling of the method, because now you write `willMovetoViewController `. It must `willMoveToParentViewController`. – Neil Galiaskarov Nov 06 '13 at 19:55
  • There is an error in this code, addChildViewController calls willMoveToParentViewController. please see https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html#//apple_ref/doc/uid/TP40007457-CH18-SW6 – Oliver Atkinson Nov 06 '13 at 20:02
  • 2
    This works! Thank you so much for all the effort you went through!! You're amazing!!! – user2397282 Nov 06 '13 at 21:18
  • 2
    Thanks for making the github sample code - very helpful! – daspianist May 23 '14 at 03:28
  • Can we add a logic where we can see only onc controller at a time and when we do scrolling it should show the complete controller on the basis of controller occupying more percentage area. – kalim sayyad Aug 19 '15 at 09:33
  • very good answer, and also thank you very much for your github source code. The only problem in your project, is that when you scroll the scrollview, it does not stop on each of the view controllers and behaves like a normal horizontal scrolling rather than paging. I suggest updating your answer and code, and set the "paging enabled" in the attributes inspector for the scrollview. – Reza Shayestehpour Jan 21 '16 at 21:35
  • @RezaShayestehpour What you're describing is a `UIPageViewController` – jjatie Nov 28 '16 at 20:07
  • 1
    @jjatie sometimes you don't want to have a whole view controller and just want to have the paging enabled in a scroll view that is inside another view controller. – Reza Shayestehpour Dec 04 '16 at 11:29
2
    let obj1 = self.storyboard?.instantiateViewControllerWithIdentifier("DocumentsVC") as! DocumentsVC
    let obj2 = self.storyboard?.instantiateViewControllerWithIdentifier("AppointmentsVC") as! AppointmentsVC
    let obj3 = self.storyboard?.instantiateViewControllerWithIdentifier("DashboardVC") as! DashboardVC

    self.containerScrollView.frame = obj2.view.frame

    self.containerScrollView.addSubview(obj2.view)
    obj2.willMoveToParentViewController(self)
    self.addChildViewController(obj2)

    self.containerScrollView.addSubview(obj1.view)
    obj1.willMoveToParentViewController(self)
    self.addChildViewController(obj1)

    self.containerScrollView.addSubview(obj3.view)
    obj3.willMoveToParentViewController(self)
    self.addChildViewController(obj3)

    self.containerScrollView.contentSize = CGSizeMake(3*UIScreen.mainScreen().bounds.width, 0)

    obj1.view.frame.origin =  CGPointMake(0, 0)
    obj2.view.frame.origin =  CGPointMake(UIScreen.mainScreen().bounds.width, 0)
    obj3.view.frame.origin = CGPointMake(2*UIScreen.mainScreen().bounds.width, 0)
Timo Salomäki
  • 7,099
  • 3
  • 25
  • 40
sachin
  • 21
  • 1
2

Swift 3.0

Based on Sachin answer - bit more generic - just add next element to views array

var views = [ViewController(), ViewController2(), ViewController3(), ViewController4()]

func setupScrollView() {
    scrollView.frame = views.first!.view.frame
    scrollView.contentSize = CGSize(width: CGFloat(views.count) * width, height: 0)
    _ = views.map({ addViewToScrollView($0) })
    _ = views.map({ $0.view.frame.origin =  CGPoint(x: CGFloat(views.index(of: $0)!) * width, y: 0) })
}

func addViewToScrollView(_ viewController: UIViewController) {
    scrollView.addSubview(viewController.view)
    views.willMove(toParentViewController: self)
    addChildViewController(viewController)
}
chrisco
  • 147
  • 2
  • 10
1

Try this git repo, Using this repo you can create a view navigation like Snapchat/Tinder Main Pages.

https://github.com/goktugyil/EZSwipeController

Jayesh Thanki
  • 2,037
  • 2
  • 23
  • 32