为啥在制作自定义表格视图单元格时将可重用单元格出列两次

Posted

技术标签:

【中文标题】为啥在制作自定义表格视图单元格时将可重用单元格出列两次【英文标题】:Why dequeue reusable cell twice in making custom table view cell为什么在制作自定义表格视图单元格时将可重用单元格出列两次 【发布时间】:2012-08-04 06:44:14 【问题描述】:

我正在学习使用情节提要制作自定义表格视图单元的教程。我拖动一个 UILabel 作为单元格的子视图,并将其标记设置为 1。关于数据源代码,我有两个问题。

    第二个 dequeue 语句的目的是什么?我知道这是一个 init 方法,而不是使用情节提要来制作自定义单元格。

    tableview和self.tableview有什么区别?

    -(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
    
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) 
            cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        
        NSDictionary *dToAccess = (self.tableView==tableView)?[self.arForTable objectAtIndex:indexPath.row] : [self.arForSearch objectAtIndex:indexPath.row];
        [(UILabel*)[cell viewWithTag:1] setText:[dToAccess valueForKey:@"name"]];
        [(UILabel*)[cell viewWithTag:2] setText:[dToAccess valueForKey:@"value"]];
        return cell;
    
    

【问题讨论】:

有人可以帮忙格式化吗?我无法将第一行代码放入代码块中 我尝试修复代码格式,看起来语法突出显示正在起作用。 @NSPostWhenIdle 这是编号列表,后跟一个代码块。您必须双缩进代码,因此它使代码块成为列表的一部分,或者在列表的末尾和代码块的开头之间添加一个非缩进字符。 @jrturton 啊,酷。很高兴知道,我最近遇到过几次,但真的不知道该怎么做。 这段代码毫无意义。我建议你再找一个教程。 【参考方案1】:

对于您的第一个问题,第二个 dequeueReusableCellWithIdentifier: 看起来像是一个错误。

这是 UITableView 的工作原理:

您的表格中可能有 50 行,但如果一次只有 10 行可见,您只需要制作 10 个单元格,然后当用户滚动时,您可以重复使用已离开屏幕的单元格,而不是总是释放它们并初始化屏幕上出现的新单元格。 UITableView 会保存已离开屏幕的单元格列表,当您调用 dequeueReusableCellWithIdentifier: 时,它会将其从屏幕外单元格列表中删除并将其返回给您。从这里您可以自定义单元格以供重复使用(更改其文本、颜色等)并将其返回。同样,这不是“init”方法,而是返回一个预先存在的单元格。

那么,让我们看看当这个 UITableView 第一次显示时会发生什么——在这个例子中,有 10 个可见单元格,所以 tableView 将调用 tableView:cellForRowAtIndexPath: 10 次来让单元格显示在这 10 个插槽中。每次调用它时,您都需要初始化并返回一个新的 UITableViewCell 来显示。 (此时 dequeueReusableCellWithIdentifier: 将返回 nil,因为您还没有任何可重复使用的屏幕外单元格)

当用户滚动您的列表时,单元格将开始离开屏幕,并且需要出现新的单元格。您不需要创建新单元格,因为您已经创建了一次需要在屏幕上显示的多个单元格。您应该调用 dequeueReusableCellWithIdentifier: 来获取对已离开屏幕的单元格的引用,然后您可以重新使用它。

我会这样修改你的代码:

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];

if (cell == nil) 
    cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
                                   reuseIdentifier: CellIdentifier] autorelease];

现在您在创建新单元之前检查可重复使用的单元。

关于第二个问题,

在您的示例中,tableView 指的是传入的 tableView(请参阅方法签名中的“tableView”)。另外,如果您的类定义了一个名为 tableView 的属性,那么 self.tableView 将调用该属性的 getter。

【讨论】:

【参考方案2】:

当苹果为第一部 iphone 开发 UITableView 时,他们在滚动浏览它时遇到了性能问题。然后一位聪明的工程师发现,造成这种情况的原因是分配对象是有代价的,所以他想出了一种重用单元格的方法。

dequeueReusableCellWithIdentifier 方法用于返回一个已被标记为准备重用的单元格。

因此,每当表格视图中有很多行并且您要滚动它时,滚动之前刚刚从上一个屏幕传递的单元格将被重用,而不是创建新的单元格。

并且要知道你的第二个问题的答案。我认为你应该参考这个链接:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/17669-when-use-self-objectname-just-objectname.html

【讨论】:

很高兴知道。但你没有回答问题。【参考方案3】:

两次出队是不必要的,这段代码被破坏了。

【讨论】:

以上是关于为啥在制作自定义表格视图单元格时将可重用单元格出列两次的主要内容,如果未能解决你的问题,请参考以下文章

表视图出列可重用单元格重叠

在运行时重用具有动态布局内容的单元格

重用自定义 tableView 单元格时重复显示相同的子视图(Swift 4.1)

按下表格单元格时将视图加载到导航视图控制器中

单击表格单元格时将 UIViewController 滚动到顶部

单击表格单元格时将变量值发送到下一个视图控制器