创建无限滚动天数的 UIPageViewController

Creating UIPageViewController with Infinite Scrolling Through Days

我的应用程序中有一个由 UIPageViewController 控制的日志。页面的视图控制器工作正常,但 UIPageViewController 有一些不稳定的行为。首先,委托方法(页面视图控制器是它自己的委托):

private func journalPage(for date: Date) -> JournalViewController? {
    // Create a new view controller and pass suitable data.
    guard let journalPage = storyboard?.instantiateViewController(withIdentifier: JournalViewController.storyboardID) as? JournalViewController else {
        return nil
    }

    journalPage.date = date
    return journalPage
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
    guard let yesterday = calendar.date(byAdding: .day, value: -1, to: self.date) else {
        return nil
    }

    self.date = calendar.startOfDay(for: yesterday)        
    return journalPage(for: self.date)
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {

    guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: self.date) else {
        return nil
    }

    self.date = calendar.startOfDay(for: tomorrow)
    return journalPage(for: self.date)
}

我更新 UIPageViewControllerdate,然后 return 配置的期刊页面。问题是经常有重复的页面(同一日期的页面),或者跳过 page/date。我发现了 this 个问题,但不知道如何实现类似的问题。

我之前曾与 UIPageViewController 合作过,并且一直使用索引来解决这个问题,但在这种情况下,索引没有意义,因为您可以滚动到 beginning/end时间(字面意思)。

如何确保在正确的时间制作新页面以避免 duplicate/missed 日期?

我认为您必须以另一种方式对数据建模,因此创建一个包含数据数组的模型,并且(例如)使用索引访问数据以填充控制器。通过这种方式,您可以唯一地访问数据。

我是在基于 PageController 的应用程序中这样做的,从 apple 示例开始。

我有一个 class:(请参阅 apple 模板进行比较..)

class模型控制器:NSObject,UIPageViewControllerDataSource {

var myPages : [Page]?

.. }

其中 Page 是 class 描述您的单个页面。 我这样修改苹果代码:

func viewControllerAtIndex(_ index: Int) -> BaseHWTestController? {
    // Return the data view controller for the given index.

    let count = selected.count
    if (count == 0) || (index >= count) {
        return nil
    }

    // Create a new view controller and pass suitable data.

    let myController = storyboard.instantiateViewController(withIdentifier: identifier) as! CustomPageController
    // set ref. to data inside the controller:
    BaseHWTestController.dataObject = myPages[index]
    return BaseHWTestController
} 

不能用聚兰日数(JDN)作为索引号吗?

我没有使用索引就解决了这个问题(页面上的date 属性就足够了)。这会在任一方向上无限滚动,而不会创建重复项或跳过页面。

extension JournalPageViewController: UIPageViewControllerDataSource {
    /// Creates and returns a JournalViewController if it can be found in the storyboard,
    /// and sets it's date to `date`
    private func journalPage(for date: Date) -> JournalViewController? {
        // Create a new view controller and pass suitable data.
        guard let journalPage = storyboard?.instantiateViewController(withIdentifier: JournalViewController.storyboardID) as? JournalViewController else {
            return nil
        }

        journalPage.date = date
        return journalPage
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        debugPrint("Before: ", separator: "", terminator: "")
        let today = (viewController as! JournalViewController).date
        guard var yesterday = calendar.date(byAdding: .day, value: -1, to: today) else {
            return nil
        }
        yesterday = calendar.startOfDay(for: yesterday)

        return journalPage(for: yesterday)
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        debugPrint("After: ", separator: "", terminator: "")
        let today = (viewController as! JournalViewController).date
        guard var tomorrow = calendar.date(byAdding: .day, value: 1, to: today) else {
            return nil
        }
        tomorrow = calendar.startOfDay(for: tomorrow)

        return journalPage(for: tomorrow)
    }
}

extension JournalPageViewController: UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        self.date = (self.viewControllers?.first as! JournalViewController).date
    }
}