从 UILabel 子视图构造 UITableViewCell 时如何避免重复行
我正在将包含美国状态数据的字典元素数组加载到 UITableView 中,当用户向下滚动到屏幕外项目时,我遇到了重复的行 - 第 1 行在第 8 行重复,第 2 行在第 9 行重复,等等。
我已经审查了以下问题并实施了他们的一些建议(但没有成功):
2994472 - 我的 UITableView 有重复的行
7056578 - UITableView 滚动时重复单元
格UITableViewCell 是一个自定义构造,由 UILabels 创建。这是 cellForRowAtIndexPath 中的代码。
00 const int ABBREVIATION = 1, STATE = 2 // Declared outside cellForRowAtIndexPath
01 static NSString *CellIdentifier = @"Cell";
02
03 UILabel *abbreviation, *state;
04
05 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
06 if (cell == nil) {
07 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
08 reuseIdentifier:CellIdentifier];
09
10 abbreviation = [[UILabel alloc] initWithFrame:CGRectMake(7.0, 1.0, 34.0, 30.0 )];
11 abbreviation.tag = ABBREVIATION;
12 abbreviation.font = [UIFont fontWithName:@"Helvetica-Bold" size:20.0];
13 abbreviation.textAlignment = UITextAlignmentLeft;
14 abbreviation.textColor = [UIColor blackColor];
15
16 state = [[UILabel alloc] initWithFrame:CGRectMake(42.0, 1.0, 158.0, 30.0)];
17 state.tag = STATE;
18 state.font = [UIFont fontWithName:@"Helvetica-Bold" size:20.0];
19 state.textAlignment = UITextAlignmentLeft;
20 state.textColor = [UIColor blackColor];
21
22 [cell.contentView addSubview:abbreviation];
23 [cell.contentView addSubview:state];
24
25 [cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
26 [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
27 }
28
29 abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"];
30 state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"];
31
32 return cell;
按照 2994472 中的建议,我修改了第 27 行和第 28 行以使用三元运算符。
29 abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"] ?
[[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"] :
@"";
30 state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"] ?
[[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"] :
@"";
这不起作用,从第 8 行开始重复仍然发生
。解决问题的方法似乎是在设置标签文本以深入到实际子视图时引用 UILabel 标记。
29 ((UILabel *)[cell viewWithTag:ABBREVIATION]).text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"];
30 ((UILabel *)[cell viewWithTag:STATE]).text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"name"];
当以这种方式引用单元格子视图时,UITableView 行重复就会消失。
I'm loading an array of dictionary elements containing US state data into a UITableView and I'm experiencing duplicate rows when the user scrolls down to offscreen items - row 1 is duplicated at row 8, row 2 is duplicated at row 9, etc.
I've reviewed the following SO questions and implemented some of their suggestions (without success):
2994472 - My UITableView has duplicate rows
7056578 - UITableView repeating cells when scrolled
The UITableViewCell is a custom construction, created from UILabels. Here's the code in cellForRowAtIndexPath.
00 const int ABBREVIATION = 1, STATE = 2 // Declared outside cellForRowAtIndexPath
01 static NSString *CellIdentifier = @"Cell";
02
03 UILabel *abbreviation, *state;
04
05 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
06 if (cell == nil) {
07 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
08 reuseIdentifier:CellIdentifier];
09
10 abbreviation = [[UILabel alloc] initWithFrame:CGRectMake(7.0, 1.0, 34.0, 30.0 )];
11 abbreviation.tag = ABBREVIATION;
12 abbreviation.font = [UIFont fontWithName:@"Helvetica-Bold" size:20.0];
13 abbreviation.textAlignment = UITextAlignmentLeft;
14 abbreviation.textColor = [UIColor blackColor];
15
16 state = [[UILabel alloc] initWithFrame:CGRectMake(42.0, 1.0, 158.0, 30.0)];
17 state.tag = STATE;
18 state.font = [UIFont fontWithName:@"Helvetica-Bold" size:20.0];
19 state.textAlignment = UITextAlignmentLeft;
20 state.textColor = [UIColor blackColor];
21
22 [cell.contentView addSubview:abbreviation];
23 [cell.contentView addSubview:state];
24
25 [cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
26 [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
27 }
28
29 abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"];
30 state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"];
31
32 return cell;
Follow the advice in 2994472, I modifying lines 27 and 28 to use a ternary operator.
29 abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"] ?
[[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"] :
@"";
30 state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"] ?
[[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"] :
@"";
That didn't work, the duplication still occurs starting on row 8.
What appears to solve the problem is referencing the UILabel tag when setting the label text to drill down to the actual subview.
29 ((UILabel *)[cell viewWithTag:ABBREVIATION]).text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"];
30 ((UILabel *)[cell viewWithTag:STATE]).text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"name"];
When the cell subviews are referenced this way the UITableView row duplication disappears.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尽管我能够在原来的问题中发布解决方案,但我仍然想知道为什么首先会发生重复的单元格情况。
做了一些额外的研究,写出了状态的文本值和缩写值以及单元格中显示的值。
显示的结果很有趣,并且可以说明情况。
当向上滚动以显示其他状态时,会出现(空)值。
所以我认为发生的是当向下滚动发生时,第 29 行和第 30 行中的原始代码尝试设置两个实例变量的文本值。
但由于它们已被 ARC 自动取消引用,因此它们不再存在,无法设置,并返回 null 值。但是,包含原始值的单元格将“出列”并与旧数据一起重新使用,从而导致出现重复项。
让我知道我的假设是否完全错误。
Though I was able to post a solution in my original question, I still was wondering why the duplicate cell situation was happening in the first place.
Did some additional research, writing out the text values for the state and abbreviation values alongside the values displayed in the cells.
The results displayed are interesting and throw some light on the situation.
The (null) values appear when scrolling up to display additional states.
So what I think is happening is when the scrolling down happens, the original code in lines 29 and 30 attempts to set the text values of the two instance variables.
But since they've been automatically dereferenced by ARC, they don't exist anymore, cannot be set, and return a value of null. However the cells which contain the original values are "dequeued" and reused with the old data, causing duplicates to appear.
Let me know if I'm totally off base with this hypothesis.
看起来在
dequeueReusableCellWithIdentifier:
返回现有表视图单元格的情况下,因此您的if
块被跳过,您的缩写
和state
变量未设置。因此,在这种情况下(当您开始滚动并显示重用单元格时会发生这种情况),缩写和状态在函数末尾为零,因此重用单元格的标签为没有按照您的预期进行更新。您可能需要一个else
块,在其中设置缩写和状态变量以指向cell
的正确子视图。It looks like in the case that
dequeueReusableCellWithIdentifier:
returns an existing table view cell, so that yourif
block is skipped, yourabbreviation
andstate
variables are not set. So in this case (which would happen when you begin scrolling and thus displaying reused cells),abbreviation
andstate
are nil at the end of your function so the reused cell's labels are not being updated as you expect. You probably want anelse
block where you set the abbreviation and state vars to point to the correct subviews of thecell
.