2

When I call this code:

tableView.reloadRows(at: [IndexPath(item: index, section: 0)], with: .none)

tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: changeBankCardTableViewCellReuseId) as! MyCell
}

This cell dequeued is new cell, even that this cell is showing (I do not want to create a new, because my cell have a timer, it change my title)

So I change my code, like this:

let indexPath = IndexPath(item: index, section: 0)
if let cell = bundTableView.cellForRow(at: indexPath),
cell is ChangeBankCardTableViewCell {
    let myCell: ChangeBankCardTableViewCell = cell as! MyCell
    /// do some thing
}

But, this is too long, and myCell must export function to call.

dequeueReusableCell will create a new cell? Why? I think if cell exists, need not create.

hasan
  • 23,815
  • 10
  • 63
  • 101
craig wang
  • 19
  • 3
  • `UITableView` **reuses cells**. It deallocates cells when they are not visible and reuses an instance of a cell before they are needed. – Tamás Sengel Sep 29 '17 at 14:07
  • 1
    Your timer should not live in the cell. The cell object is just a view on to your model. You should be prepared for the cell to be disposed of or reused at any time. – Paulw11 Sep 29 '17 at 14:09
  • this is a good idea, but if i have ten or more cell, every cell need a timer, and cell will be reuse, it is difficulty to manage. in my app, i use mvvm mode, so, i need push timer in my viewControlle or model? – craig wang Sep 30 '17 at 06:36

2 Answers2

2

Reusable cells try to REUSE CELLS THAT WENT OUT OF SCRREN.

For example, you have 10 items to display. But if your phone can only display 5 cells, then when you scroll down to 6th cell, it reuses 1st cell(since it went out of vision) and create the 6th cell.

But remember, reuse does not mean it reset all the attribute set up you made for 1st cell. For example, you turned off isUserInteractionEnable to false for the 1st cell, then when 6th cell reuses the 1st cell then the 6th cell's isUserInteractionEnable remains false.

Bubu
  • 651
  • 8
  • 25
0

From an experience I know that reloading data on tableview lets the tableview to lose some properties values. for example the selected cell.

From your experience here it also shows that the cells get reconstructed. I am pretty sure that not only it causes you to deque new cells. its also removes the old cell from memory(nothin points to them anymore). the old cells will never used anymore even if you scroll down the table. they are gone.

Yes, you should change your code to:

let indexPath = IndexPath(item: index, section: 0)
if let cell = bundTableView.cellForRow(at: indexPath)

You think that it is too long. but, its the right way to do it. reloading cells is more costy as you experienced and there is no point of trying to force that behaviour. and I think we can't.

As Paulw11 pointed. your timers shouldnt live on the cell. it can contain a ref. to your timer for easier access when you try to change data on your cell. but you also have to include your timer on your controller data structure for every cell.

You have two solutions now:

  1. Reloading cell and you will get new cell. then you should fill it from the data structure on your controller that contains the timers.

    OR

  2. Accessing the row using bundTableView.cellForRow. and if that cell is shown you can use the data from inside it. otherwise, use the data on your controller. I would say always use the data from your controller.

The first way is obviously more costy in terms of memory and time cause you are constructing the hall cell.

hasan
  • 23,815
  • 10
  • 63
  • 101
  • if this cell is not need reuse, it is ok, i think! but, when the cell is reused, i need reduction this timer state – craig wang Sep 30 '17 at 06:38