UITableView performance optimisation to improve the smoothness of list scrolling
UITableView is a control that is most commonly used in iOS development and is the most prone to performance problems. This article lists some performance optimisation points to improve the smoothness of list scrolling.
Reuse
When the TableView needs to display a Cell, it will first find a reusable from the created Cell and then display it to the screen. In general, the cells that can be reused roll out of the screen area. If you slowly drag the TableView, you can see that the Cell is constantly being reused (through the breakpoint you can see that Cell’s init or awakeFromNib is not being called). But if you scroll quickly, you may still see that the Cell is created.
1.1 The ProtoType of the Cell has been defined in the TableView of the StoryBoard.
Then specify its ReuseIdentify, when the delegate returns to the Cell, call:
[tableView dequeueReusableCellWithIdentifier:kCellID];
1.2 Cell is loaded from a separate xib
You need to register first:
[tableView registerNib:[UINib nibWithNibName:kCellID bundle:nil] forCellReuseIdentifier:kCellID];
1.3 The number of ProtoTypes of the Cell is as small as possible, because the more types of Cells, the more the number of Cells created by the TableView, and the number of cells is multiplied.
2. Cache
Cache can basically solve most performance problems. TableView needs to know the height of the Cell to layout the Cell. You need to know the height of all the Cells to know the height of the TableView itself. Therefore, every time you call reloadData, you need to calculate the height of all the Cells. We want to minimize the complexity of height calculations.
2.1 Cache Cell Height
2.1.1 Fixed-width, single-type Cell
When creating a TableView, set its rowHeight property directly.
2.1.2 For highly fixed, diverse types of Cell
Implement the proxy method, returning different heights according to the type of Cell:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
2.1.3 For a Cell with Unfixed Height
Since the height needs to be calculated dynamically, the amount of calculation will inevitably increase, but there is still room for optimisation. A common optimisation method is to cache cellHeight as an attribute of data. For each cell corresponding to each data, only one height needs to be calculated. Sample code:
@interface ContentInfo : NSObject @property(nonatomic, assign) DetailInfo *detail;
@property(nonatomic, strong)
CGFloat cellHeight;
- (CGFloat)calcHeight;
@end- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
ContentInfo *info = _dataSource[index];
if (info.cellHeight <= 0.1) {
info.cellHeight = [info calcHeight];
}
return info.cellHeight;
}Of course, in this way, the amount of computation is placed in the proxy method of TableView. In fact, when you create ContentInfo itself, you can call its calcHeight method. In the proxy method, you can directly return info.cellHeight. But also have to choose between the actual situation, because sometimes, with a data source, but does not necessarily need to display TableView, calculating the height in advance will be a waste of time.
2.2 Cache Cell Resources
For example, every Cell that needs to use UIImage, UIFont, NSDateFormatter or any object that is needed for drawing, it is recommended to use the class-level initialization method to perform the allocation and store it as a static variable.
3. Create
3.1 Remove AutoLayout
If you find that you can’t meet the requirements when creating a Cell through StoryBoard+xib+AutoLayout, consider removing AutoLayout.
3.2 Code Creation Cell
If you don’t have problems with AutoLayout, consider creating a View of the Cell from the code.
3.3 Self-painting
If you can’t solve the problem with code creation, you can only rely on self-painting, and reload Cell’s drawRect method.
4. Rendering
4.1 Reduce the number and level of sub-views
The deeper the subview is, the more computation is required to render to the screen.
4.2 Reduce the transparent layer of the child View
For opaque View, set opaque to YES, so you don’t need to consider other content covered by View when drawing the View.
4.3 Avoid CAlayer effects.
Adding a shadow to the View in the Cell can cause performance problems, such as the following code will cause significant pinning when scrolling:
view.layer.shadowColor = color.CGColor;view.layer.shadowOffset = offset;view.layer.shadowOpacity = 1;view.layer.shadowRadius = radius;