UIPageViewController和故事板

我想从故事板中特别configuration一个UIPageViewController:

在这里输入图像描述

TutorialPageViewController.h

 #import <UIKit/UIKit.h> @interface TutorialPageViewController : UIPageViewController <UIPageViewControllerDelegate, UIPageViewControllerDataSource> @end 

TutorialPageViewController.m

 #import "TutorialPageViewController.h" @interface TutorialPageViewController () @property (assign, nonatomic) NSInteger index; @end @implementation TutorialPageViewController { NSArray *myViewControllers; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.delegate = self; self.dataSource = self; [self didMoveToParentViewController:self]; UIStoryboard *tutorialStoryboard = [UIStoryboard storyboardWithName:@"TutorialStoryboard" bundle:[NSBundle mainBundle]]; UIViewController *tuto1 = [tutorialStoryboard instantiateViewControllerWithIdentifier:@"TutorialPageViewController_1"]; UIViewController *tuto2 = [tutorialStoryboard instantiateViewControllerWithIdentifier:@"TutorialPageViewController_2"]; myViewControllers = @[tuto1, tuto2, tuto1, tuto2]; self.index = 0; [self setViewControllers:@[tuto1] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; } - (UIViewController *)viewControllerAtIndex:(NSUInteger)index { return myViewControllers[index]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger index = self.index; if (index == 0) { return nil; } // Decrease the index by 1 to return index--; return [self viewControllerAtIndex:index]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger index = self.index; index++; if (index > [myViewControllers count]) { return nil; } return [self viewControllerAtIndex:index]; } - (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController { // The number of items reflected in the page indicator. return [myViewControllers count]; } - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController { // The selected item reflected in the page indicator. return 0; } @end 

问题是…

  • 第一页与页面指示符一起显示。 在刷卡时,
  • 我可以正确看到第二页。
  • 一旦过渡完成,我会看到一个黑屏(页面指示符正确显示页码2)。 没有用户交互可用了。

2017答案..

现在, 简单地使用Storyboard就很容易做到这一点。

这些“全屏IntroPages教程”在一段时间内很受欢迎,因此我在IntroPages下面调用了这个类。

第一步,创build一个UIPageViewController的容器视图。

如果iOS新手,这是一个容器视图教程

请注意,如果您不知道如何将容器视图的“types”更改为UIPageViewController,请向下滚动到该教程的“如何更改…”部分。

在这里输入图像描述

你可以使容器任何你想要的形状 。 与任何容器视图一样,它可以是全屏或屏幕的一小部分 – 无论您想要什么。

第2步,

做四个简单的视图控制器,可以是任何你想要的 – 图像,文本,表格,任何东西。 (在这个例子中是紫色的)

四个控制器

请注意,他们只是坐在你的故事板上 ,不要链接到任何东西。

第3步,您必须设置这四个页面的ID 。 “id1”,“id2”等是好的。

设置ID

第4步,复制并粘贴! 这里是类IntroPages,

 class IntroPages: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { var pages = [UIViewController]() override func viewDidLoad() { super.viewDidLoad() self.delegate = self self.dataSource = self let p1: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "id1") let p2: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "id2") let p3: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "id3") // etc ... pages.append(p1) pages.append(p2) pages.append(p3) // etc ... setViewControllers([p1], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil) } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController)-> UIViewController? { let cur = pages.index(of: viewController)! // if you prefer to NOT scroll circularly, simply add here: // if cur == 0 { return nil } let prev = abs((cur - 1) % pages.count) return pages[prev] } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController)-> UIViewController? { let cur = pages.index(of: viewController)! // if you prefer to NOT scroll circularly, simply add here: // if cur == (pages.count - 1) { return nil } let nxt = abs((cur + 1) % pages.count) return pages[nxt] } func presentationIndex(for pageViewController: UIPageViewController)-> Int { return pages.count } } 

(看看评论 – 有你喜欢的循环或线性分页的代码。)

这就是这一切 – 你完成了。

您只需在故事板上设置过渡风格,

在这里输入图像描述

很可能你想要“滚动”,而不是另一个。

对于想要查看工作页面滚动(向前/向后)的人,

 -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger currentIndex = [myViewControllers indexOfObject:viewController]; // get the index of the current view controller on display if (currentIndex > 0) { return [myViewControllers objectAtIndex:currentIndex-1]; // return the previous viewcontroller } else { return nil; // do nothing } } -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger currentIndex = [myViewControllers indexOfObject:viewController]; // get the index of the current view controller on display // check if we are at the end and decide if we need to present // the next viewcontroller if (currentIndex < [myViewControllers count]-1) { return [myViewControllers objectAtIndex:currentIndex+1]; // return the next view controller } else { return nil; // do nothing } } 

只需要通过EditOR添加到这个伟大的答案,如果您更喜欢“全方位”分页,请执行以下操作:仍使用与EditOR相同的技术

 -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger currentIndex = [myViewControllers indexOfObject:viewController]; --currentIndex; currentIndex = currentIndex % (myViewControllers.count); return [myViewControllers objectAtIndex:currentIndex]; } -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger currentIndex = [myViewControllers indexOfObject:viewController]; ++currentIndex; currentIndex = currentIndex % (myViewControllers.count); return [myViewControllers objectAtIndex:currentIndex]; } 

UIPageViewController类的Swift代码扩展Joe Blow的答案 :

 import UIKit class MyPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { var pages = [UIViewController]() override func viewDidLoad() { super.viewDidLoad() self.delegate = self self.dataSource = self let page1: UIViewController! = storyboard?.instantiateViewControllerWithIdentifier("page1") let page2: UIViewController! = storyboard?.instantiateViewControllerWithIdentifier("page2") pages.append(page1) pages.append(page2) setViewControllers([page1], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil) } func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? { let currentIndex = pages.indexOf(viewController)! let previousIndex = abs((currentIndex - 1) % pages.count) return pages[previousIndex] } func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? { let currentIndex = pages.indexOf(viewController)! let nextIndex = abs((currentIndex + 1) % pages.count) return pages[nextIndex] } func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int { return pages.count } func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int { return 0 } } 

阅读更多有关使用UIPageViewController与容器视图与故事板设置。

故事板中的UIPageViewController似乎有很多问题。

下面是一些演示代码 ,向您展示如何使用故事板中的UIPageViewController作为独立的全屏视图或UIContainerView,如果您只想在页面的一小部分区域进行分页。

在这里输入图像描述 在这里输入图像描述 在这里输入图像描述

更新了Swift 3:

 class YourPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { var pages = [UIViewController]() override func viewDidLoad() { super.viewDidLoad() self.delegate = self self.dataSource = self let page1: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "page1") let page2: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "page2") pages.append(page1) pages.append(page2) setViewControllers([page1], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil) } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { let currentIndex = pages.index(of: viewController)! let previousIndex = abs((currentIndex - 1) % pages.count) return pages[previousIndex] } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { let currentIndex = pages.index(of: viewController)! let nextIndex = abs((currentIndex + 1) % pages.count) return pages[nextIndex] } func presentationIndex(for pageViewController: UIPageViewController) -> Int { return pages.count } } 

要使用@ samwize的答案进行无限回滚,您需要添加条件来检查负值。 否则,您只需在第一页和第二页之间切换。 这只有在您计划拥有两页以上时才有必要。

 func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { let currentIndex = pages.index(of: viewController)! var previousIndex = (currentIndex - 1) % pages.count if previousIndex < 0 {previousIndex = pages.count - 1} return pages[previousIndex] } 

问题是你不正确地重用UIViewController实例:

 myViewControllers = @[tuto1, tuto2, tuto1, tuto2]; 

我build议你有一个NSMutableSet将作为一个可重复使用的UIViewController实例池。

viewControllerBeforeViewController:viewControllerBeforeViewController:使用NSPredicatesearch你的NSMutableSet ,find一个parentViewController等于nilUIViewController 。 如果find一个,请将其退回。 如果没有,实例化一个新的,将它添加到NSMutableSet ,然后返回它。

当你完成并且你的testing通过的时候,你可以将这个池抽取到自己的类中。