2010-11-30 20 views
1

ScrollViewSuite有问题。它使用的内存比需要的多。 例如:ScrollViewSuite示例代码使用比所需内存更多的内存?

  1. 加载图像中25%和测量存储器(4 MB)
  2. 放大图像为100%,并测量存储器(30 MB)
  3. 缩小到25%,并测量存储器( 30 MB) - 为什么30?它只能使用4 MB - 这是问题所在。

如何解决问题?

/***********************************************************************************/ 
/* Most of the work of tiling is done in layoutSubviews, which we override here. */ 
/* We recycle the tiles that are no longer in the visible bounds of the scrollView */ 
/* and we add any tiles that should now be present but are missing.    */ 
/***********************************************************************************/ 

- (void)layoutSubviews 
{ 
[self updateResolution]; 
NSLog(@"layoutSubviews "); 
    [super layoutSubviews]; 

    CGRect visibleBounds = [self bounds]; 

    // first recycle all tiles that are no longer visible 
    for (UIView *tile in [tileContainerView subviews]) { 

     // We want to see if the tiles intersect our (i.e. the scrollView's) bounds, so we need to convert their 
     // frames to our own coordinate system 
     CGRect scaledTileFrame = [tileContainerView convertRect:[tile frame] toView:self]; 

     // If the tile doesn't intersect, it's not visible, so we can recycle it 
     if (! CGRectIntersectsRect(scaledTileFrame, visibleBounds)) { 
      [reusableTiles addObject:tile]; 
      [tile removeFromSuperview]; 

     } 
    } 

    // calculate which rows and columns are visible by doing a bunch of math. 
    float scaledTileWidth = [self tileSize].width * [self zoomScale]; 
    float scaledTileHeight = [self tileSize].height * [self zoomScale]; 
    int maxRow = floorf([tileContainerView frame].size.height/scaledTileHeight); // this is the maximum possible row 
    int maxCol = floorf([tileContainerView frame].size.width/scaledTileWidth); // and the maximum possible column 
    int firstNeededRow = MAX(0, floorf(visibleBounds.origin.y/scaledTileHeight)); 
    int firstNeededCol = MAX(0, floorf(visibleBounds.origin.x/scaledTileWidth)); 
    int lastNeededRow = MIN(maxRow, floorf(CGRectGetMaxY(visibleBounds)/scaledTileHeight)); 
    int lastNeededCol = MIN(maxCol, floorf(CGRectGetMaxX(visibleBounds)/scaledTileWidth)); 

    // iterate through needed rows and columns, adding any tiles that are missing 
    for (int row = firstNeededRow; row <= lastNeededRow; row++) { 
     for (int col = firstNeededCol; col <= lastNeededCol; col++) { 

      BOOL tileIsMissing = (firstVisibleRow > row || firstVisibleColumn > col || 
            lastVisibleRow < row || lastVisibleColumn < col); 

      if (tileIsMissing) { 
       UIView *tile = [dataSource tiledScrollView:self tileForRow:row column:col resolution:resolution]; 

       // set the tile's frame so we insert it at the correct position 
       CGRect frame = CGRectMake([self tileSize].width * col, [self tileSize].height * row, [self tileSize].width, [self tileSize].height); 
       [tile setFrame:frame]; 
       [tileContainerView addSubview:tile]; 

       // annotateTile draws green lines and tile numbers on the tiles for illustration purposes. 
       [self annotateTile:tile]; 

      } 
     } 
    } 

    // update our record of which rows/cols are visible 
    firstVisibleRow = firstNeededRow; firstVisibleColumn = firstNeededCol; 
    lastVisibleRow = lastNeededRow; lastVisibleColumn = lastNeededCol;    
} 

回答

0

您确定这不是因为您在放大时正在使用额外的内存,而只是为了提高性能而缓存?像UIImages这样的事情,但是当内存警告开始击中时会正确释放。增加的内存使用量不一定意味着泄漏,也不总是希望内存使用量尽可能缩小。哎呀,多数情况下,未使用的内存比已占用的内存更浪费,但可以随时取消分配以供实际使用。

0

在挤压手势(即缩小)期间,TiledScrollView类中的layoutSubviews由于实现如何工作的方式(我测量了70个图块)而获取大量图块。这会导致您观察到的内存消耗的巨大增加。

捏合手势结束时,分辨率被更新,触发对reloadData的呼叫。所有瓷砖现在都被移除,放入可重用瓷砖的队列中,并从可重用的队列中取出一组新的瓷砖。重用瓷砖的数量非常低,因为不需要很多瓷砖来匹配新的分辨率。

这使得应用程序处于可重用队列中持有大量未使用的tile的状态(准确地说64个,因为实际上只重用了6个tile),因此浪费了大量内存。

一种可能的解决方案是将可重用瓦片队列限制到某个最大数量。然而,这并没有解决实施过程中的基本缺陷,这会导致在捏过程中获得很多瓷砖。就目前而言,代码在捏缩时总是会导致内存消耗的尖峰 - 随后在捏结束时释放大部分内存,但前提是限制可重用瓦片队列。


编辑

original demo code现在的状态为 “退休的文件”。演示代码由三个示例项目组成,问题涉及“平铺”示例。

相关问题