2012-01-11 97 views
1

我在使用来自Apple的TiledScrollView3_Tiling/​Classes/​TiledScrollView.m)时遇到了一些问题,其中有时图块在我滚动和其他时间显示时不显示。为了澄清,我看到的问题类似于具有100行的表格列表,并且一次只显示10行。在您滚动浏览列表时,有时一行或多行是空白的并保持空白,因为一旦它们显示在屏幕上,就不会重新加载以确保内容在那里。然而,一旦这些空白行离开屏幕并说你回滚到它们,它们就会显示内容。TiledScrollView在滚动到该区域时不显示某些图块

它似乎是完全随机的,没有可辨别的行为模式。我知道代理方法((UIView *)tiledScrollView:(TiledScrollView *)tiledScrollView tileForRow:(int)row column:(int)column resolution:(int)resolution)正在执行,通过NSLog's。

我的问题是:
1.你有没有遇到过这种现象,你是如何解决它的?或
2.我的调试技巧非常简单。如果我想通过查看tile或子视图是否存在来隔离问题,或者imageView无法获取图像或者其渲染问题......我将如何去调试这个问题?

请注意,下面显示的委托方法是上述tiledScrollView委托方法的精简版本,其中我删除了代码的行和分辨率部分,因为如果我只是水平滚动,则不需要它。

- (UIView *)tiledScrollView:(HorizontalTiledScrollView *)tiledScrollView column:(int)column { 
NSLog(@"+++ %s +++", __PRETTY_FUNCTION__); 

// re-use a tile rather than creating a new one, if possible 
UIView *tile = [tiledScrollView dequeueReusableTile]; 

if (!tile) { 
    // the scroll view will handle setting the tile's frame, so we don't have to worry about it 
    if (tiledScrollView == self.timeHour) { 
     tile = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, TIMEHOUR_COLUMN_WIDTH, TIMEHOUR_COLUMN_HEIGHT)] autorelease]; 
    } else if (tiledScrollView == self.timeMinute) { 
     tile = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, TIMEMINUTE_COLUMN_WIDTH, TIMEMINUTE_COLUMN_HEIGHT)] autorelease]; 
    } 

    // Some of the tiles won't be completely filled, because they're on the right or bottom edge. 
    // By default, the image would be stretched to fill the frame of the image view, but we don't 
    // want this. Setting the content mode to "top left" ensures that the images around the edge are 
    // positioned properly in their tiles. 
    [tile setContentMode:UIViewContentModeTopLeft]; 
} 

for(UIView *subview in [tile subviews]) { 
    if (subview.tag != 3) { 
     [subview removeFromSuperview]; //remove all previous subviews in tile except tile annotation if present 
    } 
} 
UIImageView *imgView = [[UIImageView alloc] init]; 
UILabel *digitLabel; 

// Add blank UIImageView as filler or UIImageView with PNG or UILabel if no PNG sized correctly and offsetted from tile's origin as subviews in the tile 
if (tiledScrollView == self.timeHour) { 
    if (column < 1) { 
     imgView.frame = CGRectZero; 
     [tile addSubview:imgView]; 
     [tile bringSubviewToFront:imgView]; 
    } else { 
     int digitH = ((column - 1) % 12 + 1); 
     imgView.frame = CGRectMake(9, 0, 17, 21); 
     [imgView setContentMode:UIViewContentModeScaleToFill]; 
     if ((imgView.image = [UIImage imageNamed:[NSString stringWithFormat:@"TimeHour_%02d.png", digitH]])) { 
      [tile addSubview:imgView]; 
      [tile bringSubviewToFront:imgView]; 
     } else { 
//    NSLog(@"No TimeHour_%02d.png", digitH); 
      digitLabel = [self makeDigitLabel:digitH frame:imgView.frame fontSize:14.0]; 
      [tile addSubview:digitLabel]; 
      [tile bringSubviewToFront:digitLabel]; 
     } 
    } 
} else if (tiledScrollView == self.timeMinute) { 
//  if (column % 2) { 
//   tile.backgroundColor = [UIColor redColor]; 
//  } else { 
//   tile.backgroundColor = [UIColor blueColor]; 
//  } 
    if (column < 1) { 
     imgView.frame = CGRectZero; 
     [tile addSubview:imgView]; 
     [tile bringSubviewToFront:imgView]; 
    } else { 
     int digitM = ((column - 1) % 60); 
     imgView.frame = CGRectMake(9, 0, 16, 15); 
     [imgView setContentMode:UIViewContentModeScaleToFill]; 
     if ((imgView.image = [UIImage imageNamed:[NSString stringWithFormat:@"TimeMinute_%02d.png", digitM]])) { 
      [tile addSubview:imgView]; 
      [tile bringSubviewToFront:imgView]; 
     } else { 
      NSLog(@"No TimeMinute_%02d.png", digitM); 
      digitLabel = [self makeDigitLabel:digitM frame:imgView.frame fontSize:12.0]; 
      [tile addSubview:digitLabel]; 
      [tile bringSubviewToFront:digitLabel]; 
     } 
    } 
} 
} 
[imgView release]; 
NSLog(@"Tile: %d",[tile.subviews count]); 
return tile; 
} 

希望它很清楚。 感谢您的帮助,
Hiren

回答

1

我终于解决了这个问题!

这个问题不在上面的代码中。它在Apple的TiledScrollView的layoutSubviews方法中。有计算下面所示的最大列的代码行(最大行具有类似的计算)

int lastNeededCol = MIN(maxCol, floorf(CGRectGetMaxX(visibleBounds)/scaledTileWidth)); 

以我的情况下,该公式计算比需要一个额外的列和该列瓦片结束坐关闭屏幕。当你没有滚动并将动画设置为NO时,这很好。但是,当您在scrollview的setContentOffset方法调用中进行滚动和/或将动画设置为YES时,由于动画延迟或如果滚动速度非常慢,您有时最终会丢失一个图块。动画或移动真的很慢会导致滚动视图检测到有移动,因此调用layoutSubviews方法,其中一行代码检查哪些图块可见并删除不可见的图块。现在,如果你做得恰到好处,那么之前创建的额外磁贴会因为它仍然不在屏幕上而被删除,并且永远不会再创建,直到磁贴移动足够远以触发重新加载该磁贴。

我做的修复是改变上述行:

int lastNeededCol = MIN(maxCol, floorf((CGRectGetMaxX(visibleBounds)-0.1)/scaledTileWidth)); 

这个新公式计算在屏幕上,从而消除掉落额外的瓷砖坐的整个事情需要显示砖柱权数关闭屏幕。

我在github上创建了一个示例代码来帮助证明这一点。 https://github.com/hmistry/TiledScrollViewDebug

+0

+1!凌晨1点30分和截止日期前后,您的小代码可以让我现在就寝 - 谢谢。 – 2013-06-09 17:32:57

+0

而不是使用floorf(... - 0。1)你可以像这样使用ceilf():'int lastNeededCol = MIN(maxCol,ceilf(CGRectGetMaxX(visibleBounds)/ scaledTileWidth) - 1);' – yurish 2013-11-18 10:05:20

+0

@yurish你在模拟器和设备上验证了它吗?当时我记得尝试了几个变体的公式(我认为像你的其中一个是其中的一个,但不确定),但他们并没有工作,因为在某些情况下,他们最终放弃最后一列,当它应该显示。 – HM1 2013-11-18 18:02:19