是否有可能在UIPageViewController中以编程方式打开页面?

是否有可能在UIPageViewController以编程方式打开页面?

是的,这是可能的方法:

 - (void)setViewControllers:(NSArray *)viewControllers direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated completion:(void (^)(BOOL finished))completion;` 

这与用于在页面上设置第一个视图控制器的方法相同。 类似的,你可以使用它去其他页面。

不知道为什么viewControllers是一个数组,而不是一个单一的视图控制器?

这是因为一个页面视图控制器可以有一个“脊柱”(如在iBooks),一次显示2页的内容。 如果您一次显示1页的内容,那么只需传入1个元素的数组。

Swift中的一个例子:

 pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil) 

因为我也需要这个,所以我会详细介绍如何做到这一点。

注:我假设你使用标准的模板forms来生成你的UIPageViewController结构 – 当你调用它时,它既有modelViewController也有dataViewController 。 如果你不明白我写的是什么 – 回头创build一个使用UIPageViewController的新项目作为基础。 你会明白的。

所以,需要翻页到一个特定的页面包括设置上面列出的方法的各个部分。 对于这个练习,我假设这是一个有两个视图横向视图。 另外,我将它作为一个IBAction来实现,以便它可以通过button按下或不button来完成 – 使select器调用并传入需要的项目也很容易。

所以,对于这个例子,你需要显示两个视图控制器,并且可以select是否在书中向前或向后。

请注意,我只是硬编码到第4页和第5页,并使用前滑。 从这里你可以看到,你所需要做的就是传递variables来帮助你获得这些项目。

 -(IBAction) flipToPage:(id)sender { // Grab the viewControllers at position 4 & 5 - note, your model is responsible for providing these. // Technically, you could have them pre-made and passed in as an array containing the two items... DataViewController *firstViewController = [self.modelController viewControllerAtIndex:4 storyboard:self.storyboard]; DataViewController *secondViewController = [self.modelController viewControllerAtIndex:5 storyboard:self.storyboard]; // Set up the array that holds these guys... NSArray *viewControllers = nil; viewControllers = [NSArray arrayWithObjects:firstViewController, secondViewController, nil]; // Now, tell the pageViewContoller to accept these guys and do the forward turn of the page. // Again, forward is subjective - you could go backward. Animation is optional but it's // a nice effect for your audience. [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; // Voila' - c'est fin! } 

这是另一个单个分页视图的代码示例。 viewControllerAtIndex的实现在这里省略,它应该返回给定索引的正确的视图控制器。

 - (void)changePage:(UIPageViewControllerNavigationDirection)direction { NSUInteger pageIndex = ((FooViewController *) [_pageViewController.viewControllers objectAtIndex:0]).pageIndex; if (direction == UIPageViewControllerNavigationDirectionForward) { pageIndex++; } else { pageIndex--; } FooViewController *viewController = [self viewControllerAtIndex:pageIndex]; if (viewController == nil) { return; } [_pageViewController setViewControllers:@[viewController] direction:direction animated:YES completion:nil]; } 

页面可以通过调用来改变

 [self changePage:UIPageViewControllerNavigationDirectionReverse]; [self changePage:UIPageViewControllerNavigationDirectionForward]; 

这段代码对我很好,谢谢。

这是我做的。 一些向前或向后的方法,以及一种直接进入特定页面的方法。 它用于纵向视图中的6页文档。 如果将它粘贴到pageViewController模板的RootController的实现中,它将正常工作。

 -(IBAction)pageGoto:(id)sender { //get page to go to NSUInteger pageToGoTo = 4; //get current index of current page DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0]; NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController]; //get the page(s) to go to DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(pageToGoTo - 1) storyboard:self.storyboard]; DataViewController *secondPageViewController = [self.modelController viewControllerAtIndex:(pageToGoTo) storyboard:self.storyboard]; //put it(or them if in landscape view) in an array NSArray *theViewControllers = nil; theViewControllers = [NSArray arrayWithObjects:targetPageViewController, secondPageViewController, nil]; //check which direction to animate page turn then turn page accordingly if (retreivedIndex < (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){ [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; } if (retreivedIndex > (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){ [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL]; } } -(IBAction)pageFoward:(id)sender { //get current index of current page DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0]; NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController]; //check that current page isn't first page if (retreivedIndex < 5){ //get the page to go to DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex + 1) storyboard:self.storyboard]; //put it(or them if in landscape view) in an array NSArray *theViewControllers = nil; theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil]; //add page view [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; } } -(IBAction)pageBack:(id)sender { //get current index of current page DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0]; NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController]; //check that current page isn't first page if (retreivedIndex > 0){ //get the page to go to DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex - 1) storyboard:self.storyboard]; //put it(or them if in landscape view) in an array NSArray *theViewControllers = nil; theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil]; //add page view [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL]; } } 

我完全可能在这里错过了一些东西,但是这个解决scheme似乎比其他人提出的要简单得多。

 extension UIPageViewController { func goToNextPage(animated: Bool = true, completion: ((Bool) -> Void)? = nil) { if let currentViewController = viewControllers?[0] { if let nextPage = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) { setViewControllers([nextPage], direction: .forward, animated: animated, completion: completion) } } } } 

那么使用dataSource中的方法怎么样?

 UIViewController *controller = [pageViewController.dataSource pageViewController:self.pageViewController viewControllerAfterViewController:pageViewController.viewControllers.firstObject]; [pageViewController setViewControllers:@[controller] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil]; 

类比为落后。

Swift中

 import UIKit extension HomeViewController { // MARK: - Carousel management. func startTimerForMovingCarousel(let numberOfSecondsBetweenFiringsOfTheTimer: NSTimeInterval) { if (self.timerForMovingCarousel == nil) { self.timerForMovingCarousel = NSTimer.scheduledTimerWithTimeInterval(numberOfSecondsBetweenFiringsOfTheTimer, target: self, selector: "moveCarousel", userInfo: nil, repeats: true) } } func moveCarousel() { println("I move the carousel.") let currentContentViewControllerDisplayed = self.pageViewController!.viewControllers[0] as! ContentViewController var index: Int = currentContentViewControllerDisplayed.index if index == self.arrayViewControllers.count - 1 { index = 0 } else { ++index } let contentViewControllerToDisplay = self.arrayViewControllers[index] as! ContentViewController self.pageViewController.setViewControllers([contentViewControllerToDisplay], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil) self.pageControl.currentPage = contentViewControllerToDisplay.index } func invalidateTimerForMovingCarousel() { if (self.timerForMovingCarousel != nil) { self.timerForMovingCarousel.invalidate() self.timerForMovingCarousel = nil } } } 

然而,使用这个'self.pageViewController setViewControllers'方法调用不会在viewController上为已经被拒绝的页面调用'viewDidDissapear',而手动调用一个页面却会在被closures的页面上调用viewDidDissapear。 我相信这是我的崩溃的原因

“所提供的视图控制器的数量(0)与请求的转换所需的数量(1)不匹配”

我还需要一个button在PageViewController上向左导航,这个button应该完全符合您对滑动动作的期望。

由于我在“ pageViewController:viewControllerBeforeViewController ”里已经有了一些规则来处理自然的滑动导航,所以我希望button能够重用所有的代码,并且不能像以前一样使用特定的索引来访问页面答案确实。 所以,我必须采取一个替代解决scheme。

请注意,以下代码适用于页面视图控制器,它是我的自定义ViewController中的一个属性,其脊柱设置为中间值。

这里是我为左导航button写的代码:

 - (IBAction)btnNavigateLeft_Click:(id)sender { // Calling the PageViewController to obtain the current left page UIViewController *currentLeftPage = [_pageController.viewControllers objectAtIndex:0]; // Creating future pages to be displayed NSArray *newDisplayedPages = nil; UIViewController *newRightPage = nil; UIViewController *newLeftPage = nil; // Calling the delegate to obtain previous pages // My "pageViewController:viewControllerBeforeViewController" method returns nil if there is no such page (first page of the book). newRightPage = [self pageViewController:_pageController viewControllerBeforeViewController:currentLeftPage]; if (newRightPage) { newLeftPage = [self pageViewController:_pageController viewControllerBeforeViewController:newRightPage]; } if (newLeftPage) { newDisplayedPages = [[NSArray alloc] initWithObjects:newLeftPage, newRightPage, nil]; } // If there are two new pages to display, show them with animation. if (newDisplayedPages) { [_pageController setViewControllers:newDisplayedPages direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil]; } } 

你可以做一些非常相似的事情,从这里做一个正确的导航button。

正如@samwize指出的那样,分页的方式是通过使用

 setViewControllers:array 

这是我做的方式:我有我的数据源和委托单独。 您可以调用此方法,只更改“下一个”视图。 以前您必须应用分页规则。 也就是说,你必须检查方向和下一个控制器。 如果你在自定义数据源中使用该方法,那么你所显示的控制器数组将不会改变(因为你将在NSObject子类上使用自定义数组)。

使用你自己的数据源,该方法只是设置一个新的视图(具体的方向)。 由于您仍然可以控制正常滑动时将显示的页面。

我从昨天开始工作,最后我做了工作。 我无法完全使用标准模板,因为我有三个不同的viewControllers作为childviews:

 1 - rootViewController; 2 - model; 3 - viewControllers 3.1 - VC1; 3.2 - VC2; 3.3 - VC3. Note: all of VCs has Storyboard ID. 

我只需要在第一个VC中有一个触发button,所以我为pageViewController和model添加了一个属性:

 #import <UIKit/UIKit.h> #import "Model.h" @interface VC1 : UIViewController @property (nonatomic, strong) UIPageViewController *thePageViewController; @property (nonatomic, strong) SeuTimePagesModel *theModel; @end 

我重写了模型的init方法来传递storyboard和pageViewController作为参数,所以我可以将它们设置为我的VC1:

 - (id)initWithStoryboard:(UIStoryboard *)storyboard andPageViewController:(UIPageViewController *)controller { if (self = [super init]) { VC1 *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"VC1"]; vc1.pageViewController = controller; vc1.model = self; VC2 *vc2 = [storyboard instantiateViewControllerWithIdentifier:@"VC2"]; VC3 *vc3 = [storyboard instantiateViewControllerWithIdentifier:@"VC3"]; self.pageData = [[NSArray alloc] initWithObjects:vc1, vc2, vc3, nil]; } return self; } 

最后,我在我的vc1中添加了一个IBAction来触发pageViewController方法setViewControllers:direction:animated:completion ::

 - (IBAction)go:(id)sender { VC2 *vc2 = [_model.pages objectAtIndex:1]; NSArray *viewControllers = @[vc2]; [_pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil]; } 

注意我不需要findVC的索引,我的button把我带到了我的第二个VC,但并不难获得所有的索引,并跟踪你的childviews:

 - (IBAction)selecionaSeuTime:(id)sender { NSUInteger index = [_model.pages indexOfObject:self]; index++; VC2 *vc2 = [_model.pages objectAtIndex:1]; NSArray *viewControllers = @[vc2]; [_pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil]; } 

我希望它可以帮助你!

对于单页,我只是编辑了@Jack Humphries的答案

 -(void)viewDidLoad { counter = 0; } -(IBAction)buttonClick:(id)sender { counter++; DataViewController *secondVC = [self.modelController viewControllerAtIndex:counter storyboard:self.storyboard]; NSArray *viewControllers = nil; viewControllers = [NSArray arrayWithObjects:secondVC, nil]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; } 

如果页面控制指示当前页面是O &&您希望页面通过滚动浏览和也通过单击页面视图控制器中的自定义button,下面可能会有所帮助。

 //Set Delegate & Data Source for PageView controller [Say in View Did Load] self.pageViewController.dataSource = self; self.pageViewController.delegate = self; // Delegates called viewControllerBeforeViewController when User Scroll to previous page - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{ [_nextBtn setTitle:@"Next" forState:UIControlStateNormal]; NSUInteger index = ((PageContentViewController*) viewController).pageIndex; if (index == NSNotFound){ return nil; }else if (index > 0){ index--; }else{ return nil; } return [self viewControllerAtIndex:index]; } 

//当用户滚动到下一页时,委托调用viewControllerAfterViewController

 - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{ NSUInteger index = ((PageContentViewController*) viewController).pageIndex; if (index == NSNotFound){ return nil; }else if (index < 3){ index++; }else{ return nil; } return [self viewControllerAtIndex:index];} //Delegate called while transition of pages. The need to apply logic in this delegate is to maintain the index of current page. - (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{ buttonIndex = (int)((PageContentViewController*) pendingViewControllers.firstObject).pageIndex; 

}

 -(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{ if (buttonIndex == 0){ _backButton.hidden = true; }else if (buttonIndex == [self.pageImages count] - 1){ _backButton.hidden = false; [_nextBtn setTitle:@"Begin" forState:UIControlStateNormal]; }else{ _backButton.hidden = false; } 

}

//自定义button的(上一个和下一个)逻辑

 -(void)backBtnClicked:(id)sender{ if (buttonIndex > 0){ buttonIndex -= 1; } if (buttonIndex < 1) { _backButton.hidden = YES; } if (buttonIndex >=0) { [_nextBtn setTitle:@"Next" forState:UIControlStateNormal]; PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex]; NSArray *viewControllers = @[startingViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; } 

}

 -(void)nextBtnClicked:(id)sender{ if (buttonIndex < 3){ buttonIndex += 1; } if(buttonIndex == _pageImages.count){ //Navigate Outside Pageview controller }else{ if (buttonIndex ==3) { [_nextBtn setTitle:@"Begin" forState:UIControlStateNormal]; } _backButton.hidden = NO; PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex]; NSArray *viewControllers = @[startingViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; } 

}

 //BUTTON INDEX & MAX COUNT -(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController{ return [self.pageImages count];} -(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController{ return buttonIndex;} 
 - (void)moveToPage { NSUInteger pageIndex = ((ContentViewController *) [self.pageViewController.viewControllers objectAtIndex:0]).pageIndex; pageIndex++; ContentViewController *viewController = [self viewControllerAtIndex:pageIndex]; if (viewController == nil) { return; } [self.pageViewController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil]; } 

//现在调用这个方法

[self moveToPage];

我希望它的作品:)