我有一个应用程序在滚动视图中加载了许多视图控制器,具体取决于用户在tableview中的对象数量。因此,当我在tableview和滚动视图之间切换时,滚动视图中的视图控制器数量会根据用户在tableview中的对象数量而变化。
我使用Apple的PageControl示例代码中的代码构建滚动视图,其中包含许多视图控制器,当然经过一些修改。
- (void)loadScrollViewWithPage:(int)page
{
if (page < 0) return;
if (page >= kNumberOfPages) return;
// replace the placeholder if necessary
MainViewController *countdownController = [viewControllers objectAtIndex:page];
if ((NSNull *)countdownController == [NSNull null])
{
id occasion = [eventsArray objectAtIndex:page];
countdownController = [[MainViewController alloc] initWithPageNumber:page];
[countdownController setOccasion:occasion];
[viewControllers replaceObjectAtIndex:page withObject:countdownController];
[countdownController release];
}
// add the controller's view to the scroll view
if (nil == countdownController.view.superview)
{
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
countdownController.view.frame = frame;
[scrollView addSubview:countdownController.view];
}
}
问题是当我在表视图和滚动视图(根据Instruments)之间切换时,生活视图控制器(MainViewController)的数量不断增加,即使我没有添加任何导致内存问题的新对象
我在滚动视图的viewWillDisappear中尝试了很多东西,如:
- (void) viewWillDisappear:(BOOL)animated
{
//test unloading all views
//Remove all subviews
[[scrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
//[[scrollView subviews] makeObjectsPerformSelector:@selector(release)];
//[viewControllers removeAllObjects];
for (unsigned m = 0; m < [viewControllers count]; m++)
{
//[[viewControllers objectAtIndex:m] makeObjectsPerformSelector:@selector(release)];
[viewControllers removeObjectAtIndex:m];
}
}
但它没有用。 以下是应用程序的工作原理youtube.com/watch?v=5W8v_smZSog
这是滚动视图的viewWillAppear方法:
- (void)viewWillAppear:(BOOL)animated
{
eventsArray = [[NSMutableArray alloc] init];
kNumberOfPages = [self.dataModel occasionCount];
//update the eventsArray from the dataModel
//Fill in the events Array with occasions form the data model
for (unsigned r = 0; r < kNumberOfPages; r++)
{
Occasion* occasion = [self.dataModel occasionAtIndex:r];
[eventsArray insertObject:occasion atIndex:r];
}
// view controllers are created lazily
// in the meantime, load the array with placeholders which will be replaced on demand
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < kNumberOfPages; i++)
{
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
// a page is the width of the scroll view
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.delegate = self;
pageControl.numberOfPages = kNumberOfPages;
pageControl.currentPage = currentPage;
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];
}
更新:乐器http://www.youtube.com/watch?v=u1Rd2clvMQE&feature=youtube_gdata_player
的视频录制显示负责的来电者的屏幕截图:
谢谢。
答案 0 :(得分:2)
Apple的PageControl示例代码已有2年的历史了,您可以将其视为已弃用,因为iOS 5中有一个新的容器视图控制器可以完成所有这些操作:UIPageViewController
。
您应该真正开始使用UIPageViewController
,然后根本不需要loadScrollViewWithPage方法。这将是更少的代码,更容易。
查看PhotoScroller示例代码。它已更新,以充分利用UIPageViewController
。
答案 1 :(得分:2)
如果您不想使用UIPageViewController
(请阅读我的其他答案),这是给您的。
示例项目是针对恒定页数(kNumberOfPages
)而设计的。 scrollview内容大小和视图控制器阵列的大小取决于页数。示例代码在awakeFromNib中设置了它,它只被调用一次。
因此,为了使这个动态化,您可以在页面数量发生变化时重新创建整个ContentController。您只需要为页数添加属性。
另一个选项是在页数改变时重置滚动视图和视图控制器数组。
我假设您已为事件定义了一个属性:
@property(nonatomic,retain) NSArray* eventsArray;
然后你可以添加这样的setter方法:
-(void)setEventsArray:(NSArray *)eventsArray
{
if (eventsArray != _eventsArray) {
[_eventsArray release];
_eventsArray = [eventsArray retain];
NSUInteger eventCount = [eventsArray count];
//reset scrollview contentSize
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * eventCount, scrollView.frame.size.height);
// reset content offset to zero
scrollView.contentOffset = CGPointZero;
//remove all subviews
[[scrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
pageControl.numberOfPages = eventCount;
// reset viewcontroller array
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < eventCount; i++)
{
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];
}
}
当用户切换到滚动视图时,您可以从表视图控制器中调用此方法。
答案 2 :(得分:1)
看起来你似乎没有实施Apple的View Controller Containment实践。这将使内存管理变得更加容易和安全。
另外,希望它可以为您节省很多未来的麻烦,已经有一个开源项目可以完成您所描述的内容(实现自动管理的一系列视图控制器的滚动视图)。
您可能需要查看它:RHHorizontalSwipe。
答案 3 :(得分:1)
包含多个UIViewController视图的UIScrollView概念听起来很粗略,设计听起来不太好。
话虽如此,一个潜在的问题可能是这一行:
if ((NSNull *)countdownController == [NSNull null])
你最好用这样的东西:
if (!countdownController || [countdownController isKindOfClass:[NSNull class]])
另外,您应该使用[super viewWillDisappear:animated]
方法拨打viewWillDisappear
。