我正在学习iPhone SDK,并且当在某些行上按下手指时,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];
} */
答案 0 :(得分:1)
我没有时间浏览325行代码,但最有可能导致问题的原因是重新使用tableview单元而没有先清除他们的子视图。
您看到箭头出现在未分配的单元格中,因为实际的单元格对象正在显示的前几行中重复使用。由于您有自定义子视图,因此每次单元格更改信息时都必须手动管理该子视图。
每次重复使用一个单元格时,您的第一步应该是将其清理干净到它的初始启动状态。只有这样才能将新数据加载到单元格中。
答案 1 :(得分:0)
正确的方式(Apple Docs说的方式)是在所有子视图上使用标签。如果正在创建单元格(未出列/重用),则可以正常创建单元格,但设置唯一标记(整数,但您可以使用define来使其更易于阅读)。如果单元格正在出列/重新使用,那么您将使用标记获取单元格。在线查看Apple Docs以自定义UItableViews,然后查看有关自定义tableviewcells的部分。