UIPageViewController,如何正确跳转到特定页面而不会弄乱数据源指定的顺序?

Kyl*_*yle 62 iphone objective-c ios uipageviewcontroller

我发现了一些关于如何UIPageViewController跳转到特定页面的问题,但我注意到跳跃的一个额外问题,没有任何答案似乎承认.

没有进入我的iOS应用程序的细节(类似于分页日历),这是我正在经历的.我声明了一个UIPageViewController,设置当前的视图控制器,并实现一个数据源.

// end of the init method
        pageViewController = [[UIPageViewController alloc] 
        initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
          navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                        options:nil];
        pageViewController.dataSource = self;
        [self jumpToDay:0];
}

//...

- (void)jumpToDay:(NSInteger)day {
        UIViewController *controller = [self dequeuePreviousDayViewControllerWithDaysBack:day];
        [pageViewController setViewControllers:@[controller]
                                    direction:UIPageViewControllerNavigationDirectionForward
                                     animated:YES
                                   completion:nil];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
        NSInteger days = ((THDayViewController *)viewController).daysAgo;
        return [self dequeuePreviousDayViewControllerWithDaysBack:days + 1];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
        NSInteger days = ((THDayViewController *)viewController).daysAgo;
        return [self dequeuePreviousDayViewControllerWithDaysBack:days - 1];
}

- (UIViewController *)dequeuePreviousDayViewControllerWithDaysBack:(NSInteger)days {
        return [[THPreviousDayViewController alloc] initWithDaysAgo:days];
}
Run Code Online (Sandbox Code Playgroud)

编辑注意:我为出列方法添加了简化代码.即使有这个亵渎的实现,我也有与页面顺序完全相同的问题.

初始化全部按预期工作.增量分页也都可以正常工作.问题是,如果我jumpToDay再次打电话,订单会混乱.

如果用户在第-5天并且跳到第1天,则向左滚动将再次显示第-5天而不是适当的第0天.这似乎与如何UIPageViewController保持对附近页面的引用有关,但我可以找不到任何会强制它刷新缓存的方法的引用.

有任何想法吗?

dji*_*i33 84

编程iOS6,由Matt Neuburg记录这个确切的问题,我实际上发现他的解决方案比目前接受的答案感觉好一些.该解决方案效果很好,具有负面的副作用,即在之前/之后动画到图像,然后用所需页面进行剧烈的替换.我觉得这是一种奇怪的用户体验,Matt的解决方案可以解决这个问题.

__weak UIPageViewController* pvcw = pvc;
[pvc setViewControllers:@[page]
              direction:UIPageViewControllerNavigationDirectionForward
               animated:YES completion:^(BOOL finished) {
                   UIPageViewController* pvcs = pvcw;
                   if (!pvcs) return;
                   dispatch_async(dispatch_get_main_queue(), ^{
                       [pvcs setViewControllers:@[page]
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:NO completion:nil];
                   });
               }];
Run Code Online (Sandbox Code Playgroud)

  • 任何人都可以提供这个的快速版本?请. (3认同)

小智 37

所以我遇到了和你一样的问题,我需要能够"跳转"到一个页面,然后当我打开一个页面时发现'命令乱了'.据我所知,页面视图控制器肯定会缓存视图控制器,当你"跳转"到页面时,你必须指定方向:前进或后退.然后假设新视图控制器是前一个视图控制器的"邻居",因此当您回击时自动呈现先前的视图控制器.我发现这只发生在你使用的时候UIPageViewControllerTransitionStyleScroll而不是UIPageViewControllerTransitionStylePageCurl.页面卷曲样式显然不会执行相同的缓存,因为如果您"跳转"到某个页面然后向后回拨它会将pageViewController:viewController(Before/After)ViewController:消息传递到数据源,从而使您能够提供正确的邻居视图控制器.

解决方案:当执行"跳转"到页面时,您可以首先跳转到跳转到页面的邻居页面(animated:NO),然后在该跳转的完成块中跳转到所需页面.这将更新缓存,以便在您回拨时,将显示正确的邻居页面.缺点是你需要创建两个视图控制器; 你跳到的那个和手势后应该显示的那个.

以下是我为其编写的类别的代码UIPageViewController:

@implementation UIPageViewController (Additions)

 - (void)setViewControllers:(NSArray *)viewControllers direction:(UIPageViewControllerNavigationDirection)direction invalidateCache:(BOOL)invalidateCache animated:(BOOL)animated completion:(void (^)(BOOL finished))completion {
    NSArray *vcs = viewControllers;
    __weak UIPageViewController *mySelf = self;

    if (invalidateCache && self.transitionStyle == UIPageViewControllerTransitionStyleScroll) {
        UIViewController *neighborViewController = (direction == UIPageViewControllerNavigationDirectionForward
                                                    ? [self.dataSource pageViewController:self viewControllerBeforeViewController:viewControllers[0]]
                                                    : [self.dataSource pageViewController:self viewControllerAfterViewController:viewControllers[0]]);
        [self setViewControllers:@[neighborViewController] direction:direction animated:NO completion:^(BOOL finished) {
            [mySelf setViewControllers:vcs direction:direction animated:animated completion:completion];
        }];
    }
    else {
        [mySelf setViewControllers:vcs direction:direction animated:animated completion:completion];
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

你可以做些什么来测试这个是创建一个新的'基于页面的应用程序'并添加一个'转到'按钮,它将"跳转"到某个日历月,然后回击.务必设置要过渡的过渡样式.

  • 顺便说一句,当我在setViewControllers中将动画设置为NO时:方向:动画:完成它不会搞乱订单..!我猜这种"缓存"仅在我们为setViewControllers设置动画时才会发生. (2认同)

jce*_*ile 5

我使用这个功能(我总是在风景,2页模式)

-(void) flipToPage:(NSString * )index {


int x = [index intValue];
LeafletPageContentViewController *theCurrentViewController = [self.pageViewController.viewControllers   objectAtIndex:0];

NSUInteger retreivedIndex = [self indexOfViewController:theCurrentViewController];

LeafletPageContentViewController *firstViewController = [self viewControllerAtIndex:x];
LeafletPageContentViewController *secondViewController = [self viewControllerAtIndex:x+1 ];


NSArray *viewControllers = nil;

viewControllers = [NSArray arrayWithObjects:firstViewController, secondViewController, nil];


if (retreivedIndex < x){

    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];

} else {

    if (retreivedIndex > x ){

        [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL];
      } 
    }
} 
Run Code Online (Sandbox Code Playgroud)


con*_*ile 5

这是我的Swift解决方案,用于以下子类UIPageViewController:

假设您存储一个viewControllers数组viewControllerArray和当前页面索引updateCurrentPageIndex.

  private func slideToPage(index: Int, completion: (() -> Void)?) {
    let tempIndex = currentPageIndex
    if currentPageIndex < index {
      for var i = tempIndex+1; i <= index; i++ {
        self.setViewControllers([viewControllerArray[i]], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: {[weak self] (complete: Bool) -> Void in
          if (complete) {
            self?.updateCurrentPageIndex(i-1)
            completion?()
          }
          })
      }
    }
    else if currentPageIndex > index {
      for var i = tempIndex - 1; i >= index; i-- {
        self.setViewControllers([viewControllerArray[i]], direction: UIPageViewControllerNavigationDirection.Reverse, animated: true, completion: {[weak self] (complete: Bool) -> Void in
          if complete {
            self?.updateCurrentPageIndex(i+1)
            completion?()
          }
          })
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

47324 次

最近记录:

6 年,1 月 前