我在使用Apple的TiledScrollView
(3_Tiling/Classes/TiledScrollView.m)时遇到了一些问题,有时瓷砖在我滚动时没有显示,有时则会显示。为了澄清,我看到的问题类似于拥有100行的tableview列表,一次只显示10行。当您滚动列表时,有时一行或多行是空白的并保持空白,因为一旦它们显示在屏幕上,就不会重新加载以确保内容存在。但是,一旦这些空白行离开屏幕并说你回滚到它们,它们就会显示内容。
它的行为似乎是完全随机的,没有明显的模式。我知道委托方法((UIView *)tiledScrollView:(TiledScrollView *)tiledScrollView tileForRow:(int)row column:(int)column resolution:(int)resolution)
正在通过NSLog
执行。
我的问题是:
你有没有遇到这种现象,你是如何解决的?或
我的调试技巧非常简陋。如果我想通过查看tile或子视图是否存在来隔离问题,或者imageView无法获取图像或者是否存在渲染问题......我将如何进行调试?
注意 - 下面显示的委托方法是上面的tilesScrollView委托方法的精简版本,其中我删除了代码的行和分辨率部分,因为如果我只是水平滚动则不需要它。
- (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;
}
希望它很清楚。
谢谢你的帮助,
西仁
答案 0 :(得分: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