先說初始化
- (UIPageViewController *)PageViewController{ if(!_PageViewController){ //書脊位置,只有在UIPageViewControllerTransitionStylePageCurl才生效 NSDictionary *options =[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:UIPageViewControllerSpineLocationMin] forKey: UIPageViewControllerOptionSpineLocationKey]; //兩個page之間的間距,只有UIPageViewControllerTransitionStyleScroll格式才生效 // NSDictionary *options =[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:0] // forKey: UIPageViewControllerOptionInterPageSpacingKey]; _PageViewController = [[ UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:options]; _PageViewController.view.backgroundColor = [UIColor clearColor]; _PageViewController.dataSource = self; _PageViewController.delegate = self; } return _PageViewController; }
然后填充內容
//填充PageView - (void)setPageViewData{ [self.controllerArray removeAllObjects]; ReadingSubViewController *subView = [self viewControllerAtIndex:0]; [self.controllerArray addObject:subView]; [self.PageViewController setViewControllers:self.controllerArray direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished) { }]; } - (ReadingSubViewController *)viewControllerAtIndex:(NSInteger)index{ NSLog(@"push%ld",index); ReadingSubViewController *subView = [[ReadingSubViewController alloc]init]; subView.pageModel = self.bookpageData[index]; subView.bookModel = self.model; subView.pageIndex = index; _open = YES; [self pushButtonClick]; return subView; }
&&重點
重點是是他內部的運行邏輯,我也是今天才完全搞清楚。
先看delegate
#pragma mark ==========PageVCDelegate========== //這個方法是返回前一個頁面,如果返回為nil,那么UIPageViewController就會認為當前頁面是第一個頁面不可以向前滾動或翻頁 - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{ NSInteger index = [self getIndex:(ReadingSubViewController *)viewController]; NSLog(@"before=%ld",index); if (index == 0 || index == NSNotFound) { return nil; } index -- ; ReadingSubViewController *playVC = [self viewControllerAtIndex:index]; if (index+1< 10) { self.pageNumberLB.text = [NSString stringWithFormat:@"0%ld/%ld",index+1,_maxPage]; }else{ self.pageNumberLB.text = [NSString stringWithFormat:@"%ld/%ld",index+1,_maxPage]; } return playVC; } //這個方法是下一個頁面,如果返回為nil,那么UIPageViewController就會認為當前頁面是最后一個頁面不可以向后滾動或翻頁 - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{ NSInteger index = [self getIndex:(ReadingSubViewController *)viewController]; if (index == NSNotFound || index == _maxPage - 1) { return nil; } NSLog(@"after=%ld",index); index ++; ReadingSubViewController *playVC = [self viewControllerAtIndex:index]; if (index+1< 10) { self.pageNumberLB.text = [NSString stringWithFormat:@"0%ld/%ld",index+1,_maxPage]; }else{ self.pageNumberLB.text = [NSString stringWithFormat:@"%ld/%ld",index+1,_maxPage]; } return playVC; } - (NSInteger)getIndex:(ReadingSubViewController *)subVC{ return subVC.pageIndex; }
如果TransitionStyle是UIPageViewControllerTransitionStylePageCurl
那么從首頁開始拖動的時候,往左拖動,會觸發viewControllerBeforeViewController這個代理方法,並不會觸發viewControllerAfterViewController代理方法。
然后每次往右拖動時只會加載一個ViewController。上面整個流程的Log如下
eadingViewController.m[88] push0 ReadingViewController.m[102] before=0 ReadingViewController.m[121] after=0 ReadingViewController.m[88] push1 ReadingViewController.m[136] 開始滾動 ReadingViewController.m[140] isCompleted:成功 ReadingViewController.m[121] after=1 ReadingViewController.m[88] push2 ReadingViewController.m[136] 開始滾動 ReadingViewController.m[140] isCompleted:成功
如果TransitionStyle是UIPageViewControllerTransitionStyleScroll
那么從首頁開始拖動,不管是往右還是往左,都肯定會viewControllerAfterViewController,為PageController加載好下個Page的ViewController。我往左拖動的Log如下
ReadingViewController.m[88] push0 ReadingViewController.m[102] before=0 ReadingViewController.m[121] after=0 ReadingViewController.m[88] push1
雖然拖動完成的代理方法沒有執行。但是 viewControllerAfterViewController方法觸發,加載好了下一頁的ViewController內容。
然后往右拖動會提前加載第三頁的內容Log如下
ReadingViewController.m[102] before=0 ReadingViewController.m[121] after=0 ReadingViewController.m[88] push1 ReadingViewController.m[136] 開始滾動 ReadingViewController.m[140] isCompleted:成功 ReadingViewController.m[121] after=1 ReadingViewController.m[88] push2
如果是開始就往右拖動的話Log如下
ReadingViewController.m[88] push0 ReadingViewController.m[121] after=0 ReadingViewController.m[88] push1 ReadingViewController.m[102] before=0 ReadingViewController.m[136] 開始滾動 ReadingViewController.m[140] isCompleted:成功 ReadingViewController.m[121] after=1 ReadingViewController.m[88] push2 ReadingViewController.m[136] 開始滾動 ReadingViewController.m[140] isCompleted:成功 ReadingViewController.m[121] after=2 ReadingViewController.m[88] push3
這是拖動到第三頁的時候,但是第四頁其實已經預加載好了。
之前一直沒有用過UIPageViewControllerTransitionStyleScroll,今天用了一次才發現自己認識的很不清晰。做下記錄
更新!
前面關於self.pageNumberLB.text,也就是當前頁碼的寫法,如果是在UIPageViewControllerTransitionStylePageCurl格式下是沒有問題的。但是如果是在UIPageViewControllerTransitionStyleScroll格式下。因為會有一個預加載,viewControllerAfterViewController會調用兩次。所以會造成有誤!
解決方法:還有兩個協議方法
//這個方法是UIPageViewController開始滾動或翻頁的時候觸發 - (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers{ ReadingSubViewController *firstVC =(ReadingSubViewController *) pendingViewControllers.firstObject; NSInteger index = firstVC.pageIndex; NSLog(@"開始滾動%ld",index); _animationIndex = index; } //這個方法是在UIPageViewController結束滾動或翻頁的時候觸發 - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed{ NSLog(@"isCompleted:%@",completed?@"成功":@"失敗"); if (completed) { if (_animationIndex+1< 10) { self.pageNumberLB.text = [NSString stringWithFormat:@"0%ld/%ld",_animationIndex+1,_maxPage]; }else{ self.pageNumberLB.text = [NSString stringWithFormat:@"%ld/%ld",_animationIndex+1,_maxPage]; } } }
其實只用上面那個就可以基本滿足,不過會有輕微的拖動一下雖然沒有翻頁成功也會改變頁碼字符的現象,配合下方的方法就完美了。
OVER
2019-10-31更新
最近一個項目也用到了PageViewController,開始是UIPageViewControllerTransitionStylePageCurl,后來想用UIPageViewControllerTransitionStyleScroll,發現坑太多了,改成了UICollectionView去代替。
如果style是UIPageViewControllerTransitionStyleScroll,不推薦用PageViewController,坑太多了!!