2012-10-10 31 views
2

试图绕过某些iOS设备上发生的崩溃,并结合Apple提供的建议“不会导致分配峰值”。我怎样才能改变这个代码不会一次发生?iOS - 一次不分配太多内存

for (Item *item in self.items) { 
     ItemView *itemView = [[ItemView alloc] initWithFrame:CGRectMake(xPos, kYItemOffsetIphone, kItemWidthIphone, kItemHeightIphone) ]; 

     itemView.delegate = self; 
     [itemView layoutWithData:item]; //this just adds an imageView and button 
     [self.scrollView addSubview:itemView]; 
     xPos += kXItemSpacingIphone; 
    } 

self.items数组中有大约20个对象,用于构建20个ItemView。再一次,有没有办法让这个代码更“分配密集”?

+2

是否所有的视图可以同时显示?如果没有,你可以推迟创建一个视图直到它将要在屏幕上显示(同样,当它离开屏幕时你可以销毁一个视图[只要你稍后可以重新创建它的当前状态])。这是'UITableView'的工作原理。 –

+0

@KevinBallard是否有UIScrollView的样板代码? – soleil

+1

@soleil所以你基本上想要的是一个'UITableView'但旋转了90度? – Tommy

回答

1

我亲手做的线沿线的东西:

  1. 让我的视图控制器滚动视图的delegate(如果你这样做的代码,你必须修改视图控制器的.h说它符合UIScrollViewDelegate)。 (a)确定滚动视图的可见部分的框;以及(b)确定滚动视图的可见部分的框。 (b)确定哪个子视图与该可见部分相交; (c)加载可见的项目,并卸载那些不可见的项目。

因此,例如,它可能看起来像下面这样:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    // Determine the frame of the visible portion of the scrollview. 

    CGRect visibleScrollViewFrame = scrollView.bounds; 
    visibleScrollViewFrame.origin = scrollView.contentOffset; 

    // Now iterate through the various items, remove the ones that are not visible, 
    // and show the ones that are. 

    for (Item *itemObject in self.itemCollection) 
    { 
     // Determine the frame within the scrollview that the object does (or 
     // should) occupy. 

     CGRect itemObjectFrame = [self getItemObjectFrame:itemObject]; 

     // see if those two frames intersect 

     if (CGRectIntersectsRect(visibleScrollViewFrame, itemObjectFrame)) 
     { 
      // If it's visible, then load it (if it's not already). 
      // Personally, I have my object have a boolean property that 
      // tells me whether it's loaded or not. You can do this any 
      // way you want. 

      if (!itemObject.loaded) 
       [itemObject loadItem]; 
     } 
     else 
     { 
      // If not, go ahead and unload it (if it's loaded) to conserve memory. 

      if (itemObject.loaded) 
       [itemObject unloadItem]; 
     } 
    } 
} 

这是基本的想法。您当然可以根据您的应用程序的特定设计来优化此逻辑,但这是我通常如何做到的。

+1

很好的回答。提交者也可能实现某种可重用的视图数组,这样当项目被移出屏幕时,它们将从视图层次结构中移除并添加到此可重用视图数组中。在加载新项目时,代码可以检查是否存在已创建的可重用视图,如果是,则获取对可重用视图的引用,然后将其从阵列中移除。冲洗并重复。这与'UITableView'的实例如何在包含很多视图的非常长的列表中管理其单元格非常相似。 –

+1

@ThuggishNuggets同意。我试图保持简单,但你说得很对。 (这种出列逻辑可能属于这些'loadItem'和'unloadItem'方法。)为了获得最佳性能,他可能还想对图像进行一些缓存(我将NSCache的子类)。在滚动视图结束时它会很烦人,并且会在图像重新获取时稍微延迟一段时间。但是,我仍然试图保持简单。 – Rob