单元格索引路径滚动时没有返回预期的结果



我有一个tableview,用户使用textfield在其中编辑信息,我将该信息存储到一个数组中,该数组跟踪所有值。当用户回滚到他们已经编辑过的单元格,并且之前添加的值现在是来自其他单元格的值时,就会出现这个问题。

我理解单元格是被重用的,因此每当再次查看它们时,它们的数据需要更新。我还了解到cellforrowat在每次将cell加载到视图中时被调用,而不是仅仅在第一次创建cell时被调用。我做了一个测试项目来解决我的问题。

我第一次尝试解决这个问题是这样的

  1. cellforrowat被称为
  2. 如果这是第一次创建cell设置默认值并将其数据添加到保存cell数据的数组
  3. 如果这不是第一次,请在indexpath处从数据源绘制信息。行,并将其应用于单元格
if cellInformation.count < (indexPath.row + 1) // Newly made cell
{
cell.value = 0
cell.tField.text = ""

cellInformation[cellInformation.count] = cell

}
else if (cellInformation.count >= indexPath.row) // Cell we've seen before
{
cell.configure(Value: cellInformation[indexPath.row]!.value) // Sets the          textField.text to be the same as the cells value
}

这工作得更好,但当我滚动回我的tableview的顶部,最顶部的单元格仍然得到随机数据。我的下一个尝试为每个单元格生成一个ID标签,然后检查cellforrowat单元格的ID标签是否与数组中的任何一个相匹配。

if cellInformation.count < (indexPath.row + 1) // 0 < 1
{
cell.idTag = idTagCounter
idTagCounter += 1

cell.value = 0
cell.tField.text = ""

cellInformation[cellInformation.count] = cell
}
else if (cellInformation.count >= indexPath.row)
{
for i in 0...idTagCounter - 1
{
if(cell.idTag == cellInformation[i]?.idTag)
{
cell.configure(Value: cellInformation[i]!.value)
}
}
cell.configure(Value: cellInformation[indexPath.row]!.value)
}

这得到的结果与之前几乎相同。当我调试程序时,我意识到当我第一次向下滚动tableview时,indexPath。row从7这样的值跳到2随着我不断滚动,row离单元格的值越来越远直到它最终停在0处即使还有更多的单元格可以滚动。一旦行为0,cellforrowat将停止被调用。

关于我如何准确地将单元格值分配给我的数组中的信息的任何想法?

你的前提是错误的:

cellforrowat被称为

如果这是第一次创建单元格,则设置默认值并将其数据添加到保存单元格数据的数组

如果这不是第一次,请在indexpath处从数据源绘制信息。行,并将其应用于单元格

您应该建立一个模型对象,其中包含表视图中条目的数据,并且您的cellForRowAt()方法应该为所请求的IndexPath获取条目。

您的模型可以像一个结构体数组一样简单,表中的每个条目使用一个结构体。如果使用分段表视图,您可能需要一个数组的数组(外部数组包含节,内部数组包含每个节的条目)

应该而不是在调用cellForRowAt()中构建你的模型(数组)。

你也不应该not将单元存储到模型中。您应该存储在单元格中显示的数据(文本字符串、图像等)。)

假设cellForRowAt()可以以任意顺序请求单元格,并且可以多次请求相同的单元格。

假设我们想要显示一个动物数组和一个数字年龄:

struct Animal {
let species: String
let age: Int
}
//Create an array to hold our model data, and populate it with sample data
var animals: [Animal] = [
Animal(species: "Lion", age: 3),
Animal(species: "Tiger", age: 7),
Animal(species: "Bear", age: 4)
]
//...
func cellForRow(at indexPath: IndexPath) -> UITableViewCell? {
let cell = dequeueReusableCell(withIdentifier: "cell" for: indexPath)
let thisAnimal = animals[indexPath.row]
cell.textLabel.text = "(thisAnimal.species). Age = (thisAnimal.species)"
}

请注意,对于现代代码(iOS>=14),您应该真正使用UIListContentConfigurations来配置和构建您的单元。