UITableViewCell选择子视觉鬼
我正在学习有关iPhone SDK,并有一个有趣的例外与UITableViewCell子视图管理时,手指按在一些行上。UITableViewCell选择子视觉鬼
该表用于为手势分配声音 - 在3个方向中的一个方向上滑动手机会触发声音播放。选择一行将显示一个包含4个声音分配选项的操作表:左,下,右和取消。声音可以映射到一个,两个或三个方向,因此任何单元格都可以具有七种状态之一:左,下,右,左和下,左和右,下和右或左和右。如果一行被映射到这七个状态中的任何一个,则相应的一个或多个箭头作为子视图显示在该行的边界内。箭头在给定的屏幕和滚动时来去去去。
但是,在滚动到一批新的行后,只有当我在某些(但不是全部)行上按下手指时,箭头才会奇迹般地出现在所选状态背景中。当我将手指从行中抬起并出现操作表时,箭头消失。按下任意四个按钮之后,我无法再复制这个。但是看到这个箭头在屏幕上闪烁,因为选定的行没有被分配给任何东西,所以很迷惑和困惑。
我还没有想过在这里看到什么?我所有的表格代码都粘贴在下面,这是问题的屏幕录像:http://www.screencast.com/users/JonathanGCohen/folders/Jing/media/d483fe31-05b5-4c24-ab4d-70de4ff3a0bf
我是否管理我的子视图有错误或者是否存在我缺少的选定状态属性?还有别的吗?我是否应该在这篇文章中包含更多信息以使事情更清楚?谢谢!!
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [categories objectAtIndex:section];
NSArray *nameSection = [categoriesSounds objectForKey:key];
static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
SectionsTableIdentifier];
NSArray *sound = [categoriesSounds objectForKey:key];
NSString *soundName = [[sound objectAtIndex: row] objectAtIndex: 0];
NSString *soundOfType = [[sound objectAtIndex: row] objectAtIndex: 1];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SectionsTableIdentifier] autorelease];
}
cell.textLabel.text = [[nameSection objectAtIndex:row] objectAtIndex: 0];
NSUInteger soundSection = [[[sound objectAtIndex: row] objectAtIndex: 2] integerValue];
NSUInteger soundRow = [[[sound objectAtIndex: row] objectAtIndex: 3] integerValue];
NSUInteger leftRow = [leftOldIndexPath row];
NSUInteger leftSection = [leftOldIndexPath section];
if (soundRow == leftRow && soundSection == leftSection && leftOldIndexPath !=nil){
[selectedSoundLeftAndDown removeFromSuperview];
[selectedSoundLeftAndRight removeFromSuperview];
[cell.contentView addSubview: selectedSoundLeft];
selectedSoundLeft.frame = CGRectMake(200,8,30,30);
}
else {
[cell.contentView sendSubviewToBack: selectedSoundLeft];
}
NSUInteger downRow = [downOldIndexPath row];
NSUInteger downSection = [downOldIndexPath section];
if (soundRow == downRow && soundSection == downSection && downOldIndexPath !=nil){
[selectedSoundLeftAndDown removeFromSuperview];
[selectedSoundDownAndRight removeFromSuperview];
[cell.contentView addSubview: selectedSoundDown];
selectedSoundDown.frame = CGRectMake(200,8,30,30);
}
else {
[cell.contentView sendSubviewToBack: selectedSoundDown];
}
NSUInteger rightRow = [rightOldIndexPath row];
NSUInteger rightSection = [rightOldIndexPath section];
if (soundRow == rightRow && soundSection == rightSection && rightOldIndexPath !=nil){
[selectedSoundDownAndRight removeFromSuperview];
[selectedSoundLeftAndRight removeFromSuperview];
[cell.contentView addSubview: selectedSoundRight];
selectedSoundRight.frame = CGRectMake(200,8,30,30);
}
else {
[cell.contentView sendSubviewToBack: selectedSoundRight];
}
// combos
if (soundRow == leftRow && soundRow == downRow &&
soundSection == leftSection && soundSection == downSection){
[selectedSoundLeft removeFromSuperview];
[selectedSoundDown removeFromSuperview];
[selectedSoundLeftAndDownAndRight removeFromSuperview];
[cell.contentView addSubview: selectedSoundLeftAndDown];
selectedSoundLeftAndDown.frame = CGRectMake(200,8,30,30);
}
else {
[cell.contentView sendSubviewToBack: selectedSoundLeftAndDown];
}
if (soundRow == leftRow && soundRow == rightRow &&
soundSection == leftSection && soundSection == rightSection){
[selectedSoundLeft removeFromSuperview];
[selectedSoundRight removeFromSuperview];
[selectedSoundLeftAndDownAndRight removeFromSuperview];
[cell.contentView addSubview: selectedSoundLeftAndRight];
selectedSoundLeftAndRight.frame = CGRectMake(200,8,30,30);
}
else {
[cell.contentView sendSubviewToBack: selectedSoundLeftAndRight];
}
if (soundRow == downRow && soundRow == rightRow &&
soundSection == downSection && soundSection == rightSection){
[selectedSoundDown removeFromSuperview];
[selectedSoundRight removeFromSuperview];
[selectedSoundLeftAndDownAndRight removeFromSuperview];
[cell.contentView addSubview: selectedSoundDownAndRight];
selectedSoundDownAndRight.frame = CGRectMake(200,8,30,30);
}
else {
[cell.contentView sendSubviewToBack: selectedSoundDownAndRight];
}
if (soundRow == leftRow && soundRow == downRow && soundRow == rightRow &&
soundSection == leftSection && soundSection == downSection && soundSection == rightSection){
[selectedSoundLeftAndDown removeFromSuperview];
[selectedSoundLeftAndRight removeFromSuperview];
[selectedSoundDownAndRight removeFromSuperview];
[selectedSoundLeft removeFromSuperview];
[selectedSoundDown removeFromSuperview];
[selectedSoundRight removeFromSuperview];
[cell.contentView addSubview: selectedSoundLeftAndDownAndRight];
selectedSoundLeftAndDownAndRight.frame = CGRectMake(200,8,30,30);
}
else {
[cell.contentView sendSubviewToBack: selectedSoundLeftAndDownAndRight];
}
[indexPath retain];
return cell;
}
只是想对这篇文章进行更新。我昨天花了12个小时试图解决这个问题,这超出了我目前的技能。我将单元格选择风格设置为无,这很糟糕,但现在是时候投入毛巾了。
我完全抛弃该代码有利于下面的方法,它检查了所有当前可见的指数路径,分配给声音的索引路径的存在,然后除去子视图酌情:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
/* NSArray *allVisibleCells = [table visibleCells];
leftIsVisible = FALSE;
downIsVisible = FALSE;
rightIsVisible = FALSE;
NSLog(@"\n\n\n", (leftIsVisible ? @"TRUE" : @"FALSE"));
NSLog(@"Start: %@\n", (leftIsVisible ? @"TRUE" : @"FALSE"));
for (UITableViewCell *visibleCell in allVisibleCells){
NSIndexPath *visibleCellIndexPath = [table indexPathForCell: visibleCell];
NSLog(@"visible cell index path %@\n", visibleCellIndexPath);
if ([visibleCellIndexPath compare: leftOldIndexPath] == NSOrderedSame) {
leftIsVisible = TRUE;
NSLog(@"Compare successful: %@\n", (leftIsVisible ? @"TRUE" : @"FALSE"));
}
if ([visibleCellIndexPath compare: downOldIndexPath] == NSOrderedSame) {
downIsVisible = TRUE;
}
if ([visibleCellIndexPath compare: rightOldIndexPath] == NSOrderedSame){
rightIsVisible = TRUE;
}
}
NSLog(@"After the first fast enumeration: %@\n", (leftIsVisible ? @"TRUE" : @"FALSE"));
NSLog(@"After check for left is still visible %@\n", (leftIsVisible ? @"TRUE" : @"FALSE"));
if(leftIsVisible == FALSE){
[selectedSoundLeft removeFromSuperview];
[selectedSoundLeftAndDown removeFromSuperview];
[selectedSoundLeftAndRight removeFromSuperview];
[selectedSoundLeftAndDownAndRight removeFromSuperview];
}
if(downIsVisible == FALSE){
[selectedSoundDownAndRight removeFromSuperview];
[selectedSoundDown removeFromSuperview];
}
if (rightIsVisible == FALSE){
[selectedSoundRight removeFromSuperview];
} */
我不没有时间去浏览325行代码,但是最可能导致你的问题的是重用tableview单元格,而没有先清除它们的子视图。
您会看到箭头出现在未指定的单元格中,因为实际的单元格对象将从显示的前几行重新使用。由于您有自定义子视图,因此每次单元格更改信息时都必须手动管理该子视图。
每次你重复使用一个单元格时,你的第一步应该是将它擦干净,直到它的初始状态。只有这样你才能将新数据加载到单元格中。
正确的方式(以及Apple Docs的说法)是在所有子视图上使用标签。如果单元格正在创建(未出队/重用),那么您可以像常规那样创建单元格,但设置了唯一标记(整数,尽管您可以使用define来使其更易于阅读)。如果该单元正在出列/重用,那么您使用标签获取单元格。在Apple Docs中查找自定义UItableViews以及关于自定义tableviewcells的一节。
包括屏幕截图,但325行代码的优点在这种格式中过度且无法阅读。你应该能够将问题缩小到50行以下。即使你不能,你也应该使用PasteBin或类似的服务发布很长的代码。否则,很少有人会麻烦阅读它。 – TechZen 2010-04-02 14:30:37
感谢TechZen - 我将代码范围缩小到问题可能来自哪里。对我而言有趣的是,我只在选定状态期间看到子视图。但是我确信在擦拭板岩时我需要做得更好。 – 2010-04-02 14:41:49