关于UITableView如何重用单元格的几个问题

时间:2016-05-03 19:52:28

标签: ios swift uitableview

以下所有问题均基于使用此方法:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("CustomUserTableViewCell", forIndexPath: indexPath) as! CustomUserTableViewCell
    cell.user_id = items[indexPath.row]
    return cell
}
  1. 说UITableView是否会限制创建UITableViewCell的实例的数量是否有效?
  2. 当一个单元格实例被"重复使用"时,是否会自动重置所有实例变量?如果没有,我应该编写一个方法resetCell(),它重置实例变量,然后在willDisplayCell委托中调用它吗?
  3. 我希望我的小区每次收到通知中心帖子时都会更新。在我的单元格中,我应该将观察者添加到其通知中心?我猜我应该在listenToNotifications()内拨打willDisplayCell
  4. 同样,每次调用didEndDisplayingCell()时,是否应删除所有单元格的通知观察者?
  5. 如果我将所有重置/清除代码放在willDisplayCelldidEndDisplayingCell内,那么我应该在cellForRowAtIndexPath内放置什么?
  6. 我编写了所有代码,假设每个单元格都是它自己的实例(我没有理解"重用"单元格的概念),但现在我知道我不能这样想这一点。

2 个答案:

答案 0 :(得分:6)

  1. 表视图将创建您已注册的每种类型单元格的实例。从那里,它将创建许多实例,它需要在屏幕上完全显示自己。如果屏幕可以容纳10个细胞,那么将有10个可重复使用的细胞。
  2. 重用是一个在使用table / collectionViews时非常常见的问题。 Table / CollectionViewCells有一个方法调用prepareForReuse,专门用于指示您的内容。防止重用问题的一种方法是让拥有控制器成为管理数据的控制器。每次调用cellForRowAtIndexPath时,您都应传入相应的模型对象,然后单元格将对其进行自我配置。

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomUserTableViewCell", forIndexPath: indexPath) as! CustomUserTableViewCell
        cell.configureWithObject(items[indexPath.row])
        return cell
    }
    
    class CustomUserTableViewCell: UITableViewCell {
    
        override func prepareForReuse() {
            // set appropriate properties to nil that would incorrectly affect future cells
        }
    
        func configureWithObject(object: CustomModelObject) {
            // configure self with the passed in object
        }
    
    }
    
  3. 您可能不希望细胞观察到通知。这可能导致非常混乱的重用问题。最佳路由是让您的控制器类获取通知并在索引路径重新加载特定单元。 (如果你想让我详细说明,我可以)

  4. 我建议不按照我在第3号中所说的那样做,但如果你这样做,请将其放在单元格的deinit内。拨打电话NSNotificationCenter.DefaultCenter().removeObserver(self)
  5. 你应该把重置/清理代码放在任何地方。行的单元格将是将模型对象传递给单元格的位置。模型对象基本上只包含需要在屏幕上显示的数据。没有什么复杂的东西需要进一步处理(网络,解析,数据库提取等)。一旦单元格接收到对象,就应该根据传入的数据设置基于视图的属性。
  6. 以下是数据流的示例:

    查看模型 - 包含网络调用和从数据库中检索对象的逻辑。如果您没有数据库,可以使用它来设置您将用作数据源的任何表示。

    查看控制器 - 保留在表视图中,该视图会自动处理已注册的所有单元格的重用。您符合UITableViewDataSource,这使您有机会配置单元格。在cellForRowAtIndexPath中,您应该处于可以将单元格传递给模型对象的位置。

    通常会看到这样的电话:

    let object = dataSource.objectForIndexPath(indexPath)
    cell.configureWithObject(object)
    

    单元格 - 获取模型对象并使用该数据进行自我配置。基本模型对象将包含名为title的String属性,其值为“My Awesome Title!”。当您的单元格获取对象时,它需要做的只是titleLabel.text = modelObject.title。可以在单元格内进行一些额外的基本计算,但大多数应该事先处理。这是iOS设计模式的核心原则:MVC,MVVM等。标签通常没有太多的重用问题,特别是如果你组织这样的事情,但另一方面,图像。 prepareForReuse myImageView.image = nil通常会拨打{{1}}这样的电话。这将确保它为下次配置单元格做好准备。

答案 1 :(得分:3)

  1. 是的,将为您管理实例数。

  2. 不,他们不会自动重置。您可以覆盖UITableViewCell子类中的prepareForReuse,也可以处理cellForRowAtIndexPath中的所有案例。

  3. 假设您希望所有单元格都收听相同的通知,您可以在awakeFromNib中注册通知,如果您使用过故事板或xib,或者您可以在UITableViewCell子类中注册& #init; s init。否则,您可以cellForRowAtIndexPath

  4. 执行此操作
  5. 您应该删除deinit中的观察。如果单元格需要侦听不同的通知,您还应该删除prepareForReuse中的观察。

  6. willDisplayCell通常用于静态表视图。您应该在cellForRowAtIndexPath

  7. 中设置您的单元格