10

I'm having a UIPageViewController that shows different pages. The current behaviour is that it stops scrolling when I reached the last page. What I now want to achieve is that when on the last page and scrolling right, it goes to the first page. When at the first page, go to the last page when scrolling left. So basically let the PageViewController show the pages in circles. My first approach works quite well while having more than one page, or starting with one single page:

- (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(TMCollectionViewController *)viewController
{

    if((viewController.pageIndex) >= 1)
    {
        return _viewControllers[viewController.pageIndex - 1];
    }
    else
    {
        if ([_viewControllers count] == 1) {
            return nil;
        }
        return [_viewControllers objectAtIndex:[_viewControllers count]-1];
    }
}

But when I remove the pages so that only one is left, it still remembers either the before or after page, and shows it accordingly. Even though there is only one page left in the array. Any help is highly appreciated.

swiftBoy
  • 35,607
  • 26
  • 136
  • 135
Oliver Schobel
  • 377
  • 4
  • 20

3 Answers3

13

You can implement it as

When you are on 1st index and swipe left make its index = total count of pages

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

    if ((index == 0) || (index == NSNotFound)) {
        index = self.pageTitles.count;
    }

    index--;
    return [_viewControllers objectAtIndex:index];
}

When you are on last index set it to zero index

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

    if (index == NSNotFound) {
        return nil;
    }

    index++;
    if (index == [self.pageTitles count]) {
        index = 0;
    }
    return [_viewControllers objectAtIndex:index];
}
Heena
  • 2,348
  • 3
  • 32
  • 58
  • Hi and thanks for your quick reply. I tried your code, but it shows a similar behaviour like my own approach. It works fine when having many pages. In my app, each page represent a news source that can be added, or removed. So if a user has e.g. five sources, the code works well. Now when the user removes four of the five, and has therefore only one left in the PageViewController, one can still scroll left and right, but sees white pages with annoying flashy effects. – Oliver Schobel May 13 '14 at 11:42
  • Your count in `presentationCountForPageViewController` might not getting updated so you are getting 5 pages though it has only 1 and you are getting 4 pages white – Heena May 13 '14 at 12:39
  • The pages I'm presenting are all residing in the _viewControllers array. After a user deleted four of five pages, the _viewControllers array consists of only one ViewController. 'presentationCountForPageViewController' replies with [_viewControllers count]. But somehow doesn't help. – Oliver Schobel May 13 '14 at 14:58
  • I found out that the code I posted actually works. A bug somewhere else in my code caused the PageViewController to show more than one page even though there was only one left. After I fixed it, the PageViewController did exactly what I want it to do. Especially, when only page is left, to stop scrolling. Roshni's code works equally good, but when only one page is left, at least in my setup, it shows flashy effects when scrolling. – Oliver Schobel May 14 '14 at 13:06
4

Thanks, @Roshni

Swift 2 - Roshni's solution

func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
    var index: Int = (viewController as! PageContentViewController).index

    if index == 0 || index == NSNotFound {
        index = self.pageTitles.count
    }

    index--
    return viewControllerAtIndex(index)
}

func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
    var index: Int = (viewController as! PageContentViewController).index

    if index == NSNotFound {
        return nil
    }

    index++
    if index == self.pageTitles.count {
        index = 0
    }
    return viewControllerAtIndex(index)
}
Thomás Pereira
  • 9,589
  • 2
  • 31
  • 34
3

here is sample, I did for circular pagination

I was using Using UIPageViewController to create a content slider (Objective-C/Swift) article but thanks to @Tom Calmon and @Roshani now I am able to achieve my desired result on Swift 2.2

class PageHomeViewController: UIViewController , UIPageViewControllerDataSource{

    // MARK: - Variables
    private var pageViewController: UIPageViewController?

    // Initialize it right away here
    private let contentImages = ["nature_pic_1.png",
                                 "nature_pic_2.png",
                                 "nature_pic_3.png",
                                 "nature_pic_4.png"];

    //MARK: - View controller life cycle methods
    override func viewDidLoad() {
        super.viewDidLoad()
        createPageViewController()
        setupPageControl()
    }

   //MARK: - Create and start page view controller
    private func createPageViewController() {
        let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController
        pageController.dataSource = self

        if contentImages.count > 0 {
            let firstController = getItemController(0)!
            let startingViewControllers: NSArray = [firstController]
            pageController.setViewControllers(startingViewControllers as? [UIViewController], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
        }

        pageViewController = pageController
        addChildViewController(pageViewController!)
        self.view.addSubview(pageViewController!.view)
        pageViewController!.didMoveToParentViewController(self)
    }

    private func setupPageControl() {
        let appearance = UIPageControl.appearance()
        appearance.pageIndicatorTintColor = UIColor.grayColor()
        appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
        appearance.backgroundColor = UIColor.darkGrayColor()
    }

    // MARK: - UIPageViewControllerDataSource
    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        var index: Int = (viewController as! PageContentViewController).itemIndex

        if index == 0 || index == NSNotFound {
            index = contentImages.count
        }

        index -= 1
        return getItemController(index)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?{
        var index: Int = (viewController as! PageContentViewController).itemIndex
        if index == NSNotFound {return nil}
        index += 1
        if index == contentImages.count {index = 0}
        return getItemController(index)
    }

    private func getItemController(itemIndex: Int) -> PageContentViewController? {
        if itemIndex < contentImages.count {
            let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("PageContentViewController") as! PageContentViewController
            pageItemController.itemIndex = itemIndex
            pageItemController.imageName = contentImages[itemIndex]
            return pageItemController
        }
        return nil
    }

    // MARK: - Page Indicator
    func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
        return contentImages.count
    }
    func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
        return 0
    }

}

enter image description here

Hope this will help out there someone , someday!!

swiftBoy
  • 35,607
  • 26
  • 136
  • 135