我有一个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;
}
}
答案 0 :(得分:0)
事实证明,这是由于我的代码中实现了一种回收机制。
特别是,在ViewDidDisappear
上强制回收视图控制器的内容。在这种情况下,我已经禁用它,然后它可以正常工作。这也意味着当UIPageViewController
具有数据源并且直接管理子视图控制器时,通过滑动更改页面时不会调用ViewDidDisappear
。