preface

Last November I wrote learning this part of the content, but not only there are mistakes, their understanding is not good, now want to detailed study of tableView reuse mechanism, encountered a lot of problems in the middle, simply sort out a blog

Object pool design pattern

Re-learn the Design pattern – Object Pool pattern

Design pattern not mentioned in GoF’s work (5):Object Pool

The reuse mechanism of UITableViewCell is not some dark magic, but a creative design pattern in design patterns — object pool design pattern

The object pool pattern is a creative design pattern that uses a collection of initialized objects that are readily available from the pool. This avoids the overhead of object creation and destruction. A pool of clients requests objects in the pool and then performs operations on the returned objects. When the client ends, instead of destroying, the object is returned to the pool. This operation can be performed manually or automatically. That is, the essence of the object pool design pattern is that we get a ‘new’ object, whether it really is a new object or a recycled object.

Object pooling is primarily used to improve performance, and in some cases, object pooling can be a great performance aid. It is important to note, however, that object pooling increases the complexity of the object lifecycle because neither objects retrieved from the object pool nor objects returned to the object pool are actually created or destroyed.

The difference between registered and unregistered cell

If it is the case of registration

[tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]
Copy the code

The registration:

[tableView dequeueReusableCellWithIdentifier:@"cell"]
Copy the code

An explanation of these two methods

Register with forIndexPath:

newer dequeue method guarantees a cell is returned and resized properly, The off-queue method of updating ensures that a cell is returned and properly resized (assuming registered identifiers).Copy the code

Unregistered without forIndexPath:

Used by the delegate to acquire an already allocated cell, inThe lieu of allocating a new one delegate is used to get the allocated cells, not to allocate a new cell.Copy the code

We click to open the official Documentation in Developer Documentation:

Registered with forIndexPath:

Unregistered without:

Obviously the registration method will automatically do the job of assigning new cells instead of the registration method requiring us to manually create new cells ourselves

conclusion

If you have registered a Class for an identifier, you have registered a Class. If you have registered a Class for an identifier, you have registered a Class for an identifier.

If binding occurs, the system automatically creates a bound Cell of Class type when there is no reusable Cell in the Cell queue whose identifier is identifier.

If there is no bound Class, then we need to manually determine whether there are no reusable cells and manually create a new cell.

After registration, you do not need to worry about whether you need to create a new cell.

So each has its own good, if the style is single, the use of registration can be very convenient to solve, registration can achieve the effect. But if you want to query whether or not reuse, or detailed reuse problems, empty, you can see whether re-established, to judge more detailed, not registered may be better. But for the most part we use registration. Specific use should still divide circumstance and decide.

Cell reuse problems

Commonly understood concepts:

In layman’s terms. Let’s say we have 10 cells in our TableView, and the window only has room for the first four, and each cell is the same, and the reuse ID is the same. At this time, part of the first cell disappears, and part of the fifth cell is exposed. At this time, the first cell does not enter the reuse pool. The pool is empty, and the fifth cell naturally cannot find reusable cells in the reuse pool. The fifth cell executes the following code :(assuming we use an unregistered method to find out more about the reuse pool by nullating)

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cacheCellId];
if(! cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
Copy the code

So when a cell is created, it goes first to the if and when the fifth cell is fully displayed, and the first cell is completely out of the window, then the first cell is put into the reuse pool. As we slide up, the sixth cell will show up, and it will also go up to the code above, but it won’t go into the if, because the first cell is already in the reuse pool, and the sixth cell can reuse the first cell without having to recreate the object.

So that’s tableView reuse

Problems encountered:

But when I did my own experiments, I found some problems

By printing the address of the cell, I found that whether registered or not, the first step of the system is to create all the cells first.

Let’s say we have 10 cells in our TableView, and the window only has room for the first six, and each cell is the same, and the reuse ID is the same. At this time, part of the first cell disappears, and part of the seventh cell is exposed. At this time, the first cell does not enter the reuse pool, and the pool is empty. Naturally, the seventh cell cannot find reusable cells in the reuse pool. It will be recreated and if it’s not registered it will be nulled

But the amazing thing is that no matter registering or not registering, this step is not followed. The seventh takes up the space of the last one (same address), and the eighth takes up the space of the penultimate one. After the first and second completely disappear from view, the eighth and ninth take up the space of the first and second.

Compare the first picture

The seventh and eighth will take up the space of the last two, instead of the previous one, which is to go through the empty space, and then reapply for space. Nullifying is also performed only on the first run.

conclusion

Since tableViewCell is not open source, I think it’s difficult to summarize the rules of cell reuse from beginning to end but I learned a lot from it

  • When the screen does not display all the cells and the total number of all cells is less than 20 (both conditions are necessary), it creates all the cells and adds the ones that are not displayed to the pool. But there are problems, I don’t know why the seventh eighth takes up the last two space, found to be associated with cell line height, the height to 180, then the seventh will occupy the last space, the eighth takes up the penultimate, contrary to the front (height is 150, the seventh takes up the penultimate, eighth occupy the last one). If you change the height to 200, the seventh will only take up the last space, and by the time the eighth comes out, the first will have been added to the cache pool. If, according to other blogs, the cache pool contains a queue, first in first out, then the 7th and 8th self-spaces should go first in. If it’s a stack, there’s no way to explain why heights 180 and 150 are in reverse order. But do not consider so much, they still learned a lot of things.
  • If you can show all, no matter the total, then show how much to create as much
  • If the display is incomplete, but the total is greater than 20, then it can only create the first 20

And that’s when you get to the if where you only create the first 20, and by the time the 21st comes out, the first one hasn’t completely disappeared, so you’re back to where you started. But only the first time, if the second time down will not appear.

I’m looking forward to someone who can help me with the information I didn’t summarize above, but I’ve also learned a lot and I hope I can come back to this post when I understand it

A few tips

  • When writing a cell, we declare a static local variable for the identifier. During the entire run of the program, the local variable only takes up one copy of memory and the correct code specification is to write the cell name completely.
  • This reuse without using a tableView is a very clever way of writing it and I strongly advise against it

If some controls are reused because of reuse issues then