从 UILabel 子视图构造 UITableViewCell 时如何避免重复行

发布于 2024-12-19 11:18:46 字数 3013 浏览 3 评论 0原文

我正在将包含美国状态数据的字典元素数组加载到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

森林很绿却致人迷途 2024-12-26 11:18:46

尽管我能够在原来的问题中发布解决方案,但我仍然想知道为什么首先会发生重复的单元格情况。

做了一些额外的研究,写出了状态的文本值和缩写值以及单元格中显示的值。

(A) NSLog(@"%@", state.text);
(B) NSLog(@"%@", ((UILabel *)[cell viewWithTag:STATE]).text);

显示的结果很有趣,并且可以说明情况。

 (A)               (B)
 Iowa              Iowa
 New Hampshire     New Hampshire
 South Carolina    South Carolina
 Florida           Florida
 Nevada            Nevada
 Colorado          Colorado
 Minnesota         Minnesota
 (null)            Iowa
 (null)            New Hampshire
 (null)            SouthCarolina
 (null)            Florida

当向上滚动以显示其他状态时,会出现(空)值。

所以我认为发生的是当向下滚动发生时,第 29 行和第 30 行中的原始代码尝试设置两个实例变量的文本值。

29    abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"];
30    state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"];

但由于它们已被 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.

(A) NSLog(@"%@", state.text);
(B) NSLog(@"%@", ((UILabel *)[cell viewWithTag:STATE]).text);

The results displayed are interesting and throw some light on the situation.

 (A)               (B)
 Iowa              Iowa
 New Hampshire     New Hampshire
 South Carolina    South Carolina
 Florida           Florida
 Nevada            Nevada
 Colorado          Colorado
 Minnesota         Minnesota
 (null)            Iowa
 (null)            New Hampshire
 (null)            SouthCarolina
 (null)            Florida

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.

29    abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"];
30    state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"];

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.

冰火雁神 2024-12-26 11:18:46

看起来在 dequeueReusableCellWithIdentifier: 返回现有表视图单元格的情况下,因此您的 if 块被跳过,您的 缩写state 变量未设置。因此,在这种情况下(当您开始滚动并显示重用单元格时会发生这种情况),缩写和状态在函数末尾为零,因此重用单元格的标签为没有按照您的预期进行更新。您可能需要一个 else 块,在其中设置缩写和状态变量以指向 cell 的正确子视图。

It looks like in the case that dequeueReusableCellWithIdentifier: returns an existing table view cell, so that your if block is skipped, your abbreviation and state variables are not set. So in this case (which would happen when you begin scrolling and thus displaying reused cells), abbreviation and state are nil at the end of your function so the reused cell's labels are not being updated as you expect. You probably want an else block where you set the abbreviation and state vars to point to the correct subviews of the cell.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文