UIPageViewController在以编程方式设置时显示空白视图控制器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UIPageViewController在以编程方式设置时显示空白视图控制器相关的知识,希望对你有一定的参考价值。

我有一个UIPageViewController,其中我实现了一个缓存机制。实际上我有一个视图控制器池,当UIPageViewControllerDataSource中请求下一个或上一个视图控制器时,我尝试尽可能多地重用它们。因此,当数据源请求上一页或下一页时,我首先检查该页是否已经显示并返回相应的视图控制器。

这一切都可以使用默认的滑动手势和更改页面的内部方法。现在我需要禁用滑动手势,所以我没有设置数据源,相反,我有两个按钮可以转到上一页和下一页,并使用setViewControllers(_:direction:animated:completion:)以编程方式更改页面。它总是在同一个方向上工作正常,但是一旦我改变它,所以我使用缓存的视图控制器,它显示一个空白页面。

代码与之前完全相同,如果不是以编程方式设置视图控制器。我已尝试过有或没有动画,结果是一样的,如果我删除缓存它也很好。我的问题是,我忘了什么吗?当分配数据源时,UIPageViewController在内部执行某些操作吗?

编辑

这是代码的简化版本。这是一个Xamarin项目,但我认为这是可以理解的

public class MyPageViewController : AbstractPageViewController
{
    const int CacheCapacity = 5;

    public int initialItemId { get; set; }
    public List<int> ItemIds { get; set; }

    readonly List<ChildViewController> viewControllerCache = new List<ChildViewController>(CacheCapacity + 1);

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        DataSource = null;

        var vc = GetDocumentViewController(initialItemId);
        SetViewControllers(new[] { vc }, UIPageViewControllerNavigationDirection.Forward, false, null);

        var nextButtonItem = new UIBarButtonItem
        {
            Enabled = true
        };

        var previousButtonItem = new UIBarButtonItem
        {
            Enabled = true
        };

        nextButtonItem.Clicked += NextDocumentButton_Clicked;
        previousButtonItem.Clicked += PreviousDocumentButton_Clicked;

        var rightButtons = new UIBarButtonItem[2];
        rightButtons[0] = nextButtonItem;
        rightButtons[1] = previousButtonItem;
        NavigationItem.SetRightBarButtonItems(rightButtons, false);
    }

    private void PreviousDocumentButton_Clicked(object sender, EventArgs e)
    {
        var referenceVc = (ChildViewController)ViewControllers.FirstOrDefault();
        var referenceId = referenceVc.ItemId;

        var index = ItemIds.FindIndex(dp => dp.Id == referenceId);
        if (index < 1)
            return;

        var previousDocumentId = ItemIds[index - 1];
        var vc = GetDocumentViewController(previousDocumentId);
        SetViewControllers(new[] { vc }, UIPageViewControllerNavigationDirection.Reverse, false, null);
    }

    private void NextDocumentButton_Clicked(object sender, EventArgs e)
    {
        var referenceVc = (ChildViewController)ViewControllers.FirstOrDefault();
        var referenceId = referenceVc.ItemId;

        var index = ItemIds.FindIndex(dp => dp.Id == referenceId);
        if (index < 0 || index >= ItemIds.Count)
            return;

        var nextDocumentId = ItemIds[index + 1];
        var vc = GetDocumentViewController(nextDocumentId);
        SetViewControllers(new[] { vc }, UIPageViewControllerNavigationDirection.Forward, false, null);
    }

    ChildViewController GetDocumentViewController(int ItemId)
    {
        var cachedViewController = viewControllerCache.FirstOrDefault(dvc => dvc.ItemId == ItemId);
        if (cachedViewController != null)
            return cachedViewController;

        var vc = new ChildViewController();
        vc.SetData(itemId);
        viewControllerCache.Add(vc);

        if (viewControllerCache.Count > CacheCapacity)
        {
            viewControllerCache[0].RecycleIfNeeded();
            viewControllerCache.RemoveAt(0);
        }

        return vc;
    }
}
答案

事实证明,这是由于我的代码中实现的回收机制。

特别是,在ViewDidDisappear上强制回收视图控制器的内容。我已经在这种情况下禁用它,然后它可以正常工作。这也意味着当UIPageViewController具有数据源并且直接管理子视图控制器时,通过滑动更改页面时不会调用ViewDidDisappear

以上是关于UIPageViewController在以编程方式设置时显示空白视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式平滑滚动 UIPageViewController

UIPageViewController 内的 UITableViewController,如何防止对角拖动

iOS Swift:UIPageViewController - 以编程方式翻页

以编程方式将 UIPageViewController 过渡样式设置为滚动

是否可以在 UIPageViewController 中以编程方式翻页?

屏幕关闭时如何在 UIPageViewController 中以编程方式翻页?