【问题标题】:Swift - UIPageViewController always repeats second ViewControllerSwift - UIPageViewController 总是重复第二个 ViewController
【发布时间】:2014-09-11 18:55:36
【问题描述】:

设置:我正在尝试创建一个带有嵌入式 UIPageViewController 的 ViewController,其中包含 4 个页面,每个页面都是它们自己的 ViewController。

问题:滚动第二个视图时总是重复。例如,使用 View1、View2、View3、View4 滚动显示 View1、View2、View2、View3、View4 然后向后滚动具有 View4、View3、View3、View2、View1 的顺序,即使页面控制是准确的。

我看过很多在线教程,包括答案herehere

这是我的页面视图控制器类:

import UIKit

class HostGamePageViewController: ROLViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {

  // Constants
  let ViewControllers: NSArray = ["HostGameTest1", "HostGameTest2", "HostGameTest3", "HostGameTest4"]

  // Properties
  var pageViewController: UIPageViewController!
  var currentViewController: String!

  // UI
  @IBOutlet var pageControl: UIPageControl!

  override func viewDidLoad() {
    super.viewDidLoad()

    pageViewController = storyboard?.instantiateViewControllerWithIdentifier("HGPageViewController") as? UIPageViewController
    pageViewController.delegate = self
    pageViewController.dataSource = self

    let startingViewController = viewControllerAtIndex(0)!
    pageViewController.setViewControllers([startingViewController], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: {done in })

    addChildViewController(pageViewController)
    view.addSubview(pageViewController.view)
    pageViewController.view.frame = view.bounds
    pageViewController.didMoveToParentViewController(self)
    view.gestureRecognizers = pageViewController.gestureRecognizers

    // Setup page controls
    pageControl.numberOfPages = ViewControllers.count
    view.bringSubviewToFront(pageControl)
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  // Get the index of the current page view
  func indexOfViewController() -> Int {
    if currentViewController != nil {
      return ViewControllers.indexOfObject(currentViewController)
    }

    return NSNotFound
  }

  // Get the view controller of the given index
  func viewControllerAtIndex(index: Int) -> UIViewController? {
    if ViewControllers.count == 0 || index >= ViewControllers.count {
      return nil
    }

    pageControl.currentPage = index
    currentViewController = ViewControllers[index] as String

    return storyboard?.instantiateViewControllerWithIdentifier(currentViewController) as? ROLViewController
  }

  // Handle clicks on the page control
  @IBAction func pageControlClick(sender: UIPageControl) {
    var direction: UIPageViewControllerNavigationDirection

    if sender.currentPage < indexOfViewController() {
      direction = UIPageViewControllerNavigationDirection.Forward
    } else {
      direction = UIPageViewControllerNavigationDirection.Reverse
    }

    if let viewController = viewControllerAtIndex(sender.currentPage) {
      pageViewController.setViewControllers([viewController], direction: direction, animated: false, completion: nil)
    }
  }

  func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
    var index = indexOfViewController()

    if index == 0 || index == NSNotFound {
      return nil
    }

    index--
    return viewControllerAtIndex(index)
  }

  func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
    var index = indexOfViewController()

    if index == NSNotFound {
      return nil
    }

    index++
    if index == ViewControllers.count {
      return nil
    }

    return viewControllerAtIndex(index)
  }

}

这里是我的故事板屏幕截图的链接: http://f.cl.ly/items/0V3W133Q34170q39393Q/Image%202014-09-11%20at%2011.49.44%20AM.png

我是否错误地设置了 dateSource?我在某处读到 UIPageViewController 通过将动画设置为 false 来进行一些缓存,这是所谓的修复,但没有为我做任何事情。任何帮助将非常感激。谢谢!

【问题讨论】:

  • 我找到了解决这个问题的方法。而不是从 beforeView 和 afterView 调用返回 HostGameView1、HostGameView2 等。相反,我总是使用一个包装视图控制器,然后告诉该包装视图控制器要呈现什么视图。这似乎奏效了。

标签: ios swift uipageviewcontroller


【解决方案1】:

我遇到了一个非常相似的问题(不使用 swift,在 obj-c 中,有 3 个视图控制器,中间的一个重复了一次:“0,1,1,2”)。原来这都是关于页面视图控制器数据源方法的......

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;

我还没有真正深入研究 swift(也没有兴趣这样做),但是伪阅读您的代码让我觉得您限制了 before" 和 "after" 关键方法(swift-wise),其中变量包含在控制器内用作UIPageViewControllerDataSource,即正是我改变并解决了这个问题。

我的英语不是最好的,但我希望你能理解最后一句话。我使用的修复是基于this tutorial。就我而言,我在所有 3 种“UINavigationViewControllers”案例中使用的视图控制器,所以我创建了一个具有属性的“NavigationWrapperViewController”:

@property(assign, nonatomic) NSUInteger index;

然后,在检查关键数据源方法中的边界限制时(只显示一个,对另一个使用相同的技术):

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
   NSUInteger indice = ((NavigationWrapperViewController*)viewController).index;
   if ((indice == 0) || (indice == NSNotFound)) {
       return nil;
   }    
   return [self viewControllerAtIndex:(--indice)];
}

当在 viewControllerAtIndex 中实例化视图控制器时,不要忘记在返回它们之前正确设置该属性:

NavigationWrapperViewController *wrapperViewController = [self.storyboard instantiateViewControllerWithIdentifier:self.ViewControllers[index]];
wrapperViewController.index = index;

return wrapperViewController;

细微的区别在于显示的视图控制器的索引由当前视图控制器存储(使用简单的包装器,该类完全用于此目的,它只是在他的 .h 文件中有一个属性实现) UIPageViewControllerDataSource 负责类。

这解决了我的问题,也许是某种与线程相关的问题影响了当前获取的视图控制器索引,并导致了整个重复视图控制器的问题。

如果您愿意尝试一下,希望对您有所帮助!

【讨论】:

  • 感谢您的详尽回复!拥有一个包含当前对象数据的包装器视图似乎可以解决问题。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 2017-12-19
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多