我有一个关于启用了分页的UIScrollView的问题,其中包含许多UIView,每个UIView都由一个自己的UIViewController管理。
现在大约有20到30个UIViewControllers可以包含在UIScrollView中。它是iPad上的目录应用程序,我开始预先加载所有视图,但随着UIViewControllers的数量越来越大,这不再是一个选项。
我正在寻找内存使用方面的完美解决方案。当ScrollView的ContentOffset到达特定控制器时,重新加载UIViewControllers没有问题。我认为当ContentOffset告诉我不再需要UIViewControllers时,UIViewControllers也是如此。
处理此问题的正确方法是什么?是否足以在需要时分配UIViewControllers,将它们放入NSMutableDictionary或NSMutableArray中并在不再需要它们时将它们为零?来自已经做过类似事情的人的一点帮助会很棒!
感谢您的帮助!
答案 0 :(得分:4)
我确信那里有一些好的无限滚动类,但是如果你要“自己滚动”,这里有一个极简主义的代码,它演示了无限滚动的过程,保持当前的,前一个,和内存中的下一页,但放弃其他任何东西。这假定:
page
属性,可以跟踪它的页面;和因此,它可能看起来像:
- (void)viewDidLoad
{
[super viewDidLoad];
// my underlying model is just an array of strings, which I'll show on my child
// view; your model will be more elaborate, but I just want to illustrate the concept
self.objects = @[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"];
// set the `contentSize` for the scrollview
CGRect content = self.view.bounds;
content.size.width *= [self.objects count]; // make it wide enough to hold everything
self.scrollView.contentSize = content.size;
// set our current page and load the first pages (the first and the next pages)
self.currentPage = 0;
[self addChildPage:0 toScrollView:self.scrollView];
[self addChildPage:1 toScrollView:self.scrollView];
}
- (void)addChildPage:(NSInteger)page toScrollView:(UIScrollView *)scrollView
{
// create the child controller
ChildViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"child"];
// set whatever properties you need to in order for it to present its information correctly
controller.text = self.objects[page];
controller.page = page;
// now do the stuff to add it to the right place in the scrollview
CGRect frame = self.view.bounds;
frame.origin.x = frame.size.width * page;
controller.view.frame = frame;
[self addChildViewController:controller]; // containment call for adding child view controller
[scrollView addSubview:controller.view];
[controller didMoveToParentViewController:self]; // containment call when done adding child
}
- (ChildViewController *)childControllerForPage:(NSInteger)page
{
for (ChildViewController *controller in self.childViewControllers)
{
if (controller.page == page)
return controller;
}
return nil;
}
- (void)addChildIfNecessary:(NSInteger)page toScrollView:(UIScrollView *)scrollView
{
if (page < 0 || page >= [self.objects count])
return;
ChildViewController *controller = [self childControllerForPage:page];
if (controller == nil)
[self addChildPage:page toScrollView:scrollView];
}
- (void)removeChildController:(UIViewController *)controller
{
[controller willMoveToParentViewController:nil]; // containment call before removing child
[controller.view removeFromSuperview];
[controller removeFromParentViewController]; // containment call to remove child
}
- (void)updateChildrenViewsForPage:(NSInteger)page forScrollView:(UIScrollView *)scrollView
{
if (page == self.currentPage)
return;
// add child pages as necessary
[self addChildIfNecessary:page toScrollView:scrollView];
[self addChildIfNecessary:(page-1) toScrollView:scrollView];
[self addChildIfNecessary:(page+1) toScrollView:scrollView];
// find any pages that need removing
NSMutableArray *pagesToRemove = [NSMutableArray array];
for (ChildViewController *controller in self.childViewControllers)
{
if (controller.page < (page - 1) ||
controller.page > (page + 1))
{
[pagesToRemove addObject:controller];
}
}
// remove them if they need removing
for (UIViewController *controller in pagesToRemove)
{
[self removeChildController:controller];
}
// update our "current page" index
self.currentPage = page;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSInteger page = scrollView.contentOffset.x / scrollView.frame.size.width + 0.5;
[self updateChildrenViewsForPage:page forScrollView:scrollView];
}
这演示了适当的自定义容器调用和滚动事件的处理。我希望这会有所帮助。