1

我有一个应用程序在滚动视图中加载了许多视图控制器,具体取决于用户在表格视图中拥有的对象数量。因此,当我在 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

以及显示负责呼叫者的屏幕截图: 在此处输入图像描述

谢谢你。

4

4 回答 4

2

Apple 的 PageControl 示例代码已有 2 年历史,您可以将其视为已弃用,因为 iOS 5 中有一个新的容器视图控制器可以执行所有这些操作:UIPageViewController.

您应该真正开始使用UIPageViewController,然后您根本不需要那个 loadScrollViewWithPage 方法。这将是更少的代码,更容易。

查看PhotoScroller示例代码。它已更新以充分利用UIPageViewController.

于 2012-11-02T22:25:46.550 回答
2

如果您不想使用,这是给您的UIPageViewController(阅读我的其他答案)。

示例项目设计用于固定数量的页面 ( kNumberOfPages)。滚动视图内容大小和视图控制器数组的大小取决于页数。示例代码在仅调用一次的 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];
    }
}

当用户切换到滚动视图时,您从表视图控制器调用此方法。

于 2012-11-03T11:02:01.960 回答
1

您似乎没有实施 Apple 的View Controller Containment实践。这将使内存管理变得更加容易和安全。

另外,希望它可以为您节省很多未来的麻烦,已经有一个开源项目可以完成您所描述的工作(实现任意数量的视图控制器的自我管理滚动视图)。

您可能想看看它:RHHorizo​​ntalSwipe

于 2012-11-02T22:05:33.367 回答
1

包含多个 UIViewController 视图的 UIScrollView 的概念充其量听起来很粗略,这种设计听起来一点也不好。

话虽如此,一个潜在的问题可能是这一行:

if ((NSNull *)countdownController == [NSNull null]) 

使用这样的方法会更好:

if (!countdownController || [countdownController isKindOfClass:[NSNull class]])

此外,您应该调用[super viewWillDisappear:animated]您的viewWillDisappear方法。

于 2012-11-04T14:49:28.533 回答