In the last article, we looked at the iOS rendering loop, the off-screen rendering principle, and the lag principle. In this article, we will explore the detection of lag and how to eliminate it.
Catton’s tests
Caton time ratio
To detect Caton, we can use Instrument’s Animation Hitches to detect Caton.
In Apple’s official advice, the lag time ratio is used to measure the severity of the lag.
If the holdup time within 1s exceeds 10ms, the holdup is serious and needs to be resolved.
Animation Hitches
Next, we first of our UITableView slide to perform a lag analysis, run the App on the real machine, check the results:
The results were particularly poor: there were a lot ofSerious caton
A few caton did290ms/s
.
Time Profile
We click on the Time Profile to see the function call stack at this point and filter out the system calls
We go to the main thread call stack of our App and look at the percentage of time it’s used
It can be seen from the analysis that there are a lot of time-consuming operations in model.setter methods of cellforRow method, resulting in delay in the submission stage, resulting in lag. You can use this method to analyze the holdup in the commit phase by looking at the function call stack for each holdup in turn.
Show Optimization Opportunities
On the other hand, we can also use Xcode to check the performance of our App. In Xcode 12, click Debug View Hierarchy, and then in the Editor option, By default, Show Optimization Opportunities is checked, and Xcode will help us check for some Optimization suggestions during the running of the App.
We use a cornerRadius with a corner mask and a corner mask. The cornerRadius is a cornerRadius.
Why not mask?
inEditor
Options, selectShow Layers
:
Using CAShaperLayer + mask to create rounded corners will result in an off-screen rendering. During the scrolling of the cell, there will be hundreds or thousands of off-screen renderings submitted to the render server, resulting in stuttering.
Color Off-screen Rendered
In the simulator, go to Debug -> Color off-screen Rendered to detect the off-screen Rendered view, which will be marked yellow.
From the simulator, we can see that the container view causes an off-screen rendering.
A list of optimization
The rounded optimization
1. After iOS13, you can use the ApIcornerRadius and cornerCurve of the system.
view.layer.cornerRadius = 22
view.layer.cornerCurve = .continous
Copy the code
2. For UILabel and UIButton, you can use a cornerRadius directly.
label.layer.cornerRadius = 22
Copy the code
3. Rewrite the view’s -drawRect: method to draw rounded corners using Core Graphic
- (void)drawRect:(CGRect)rect { [super drawRect:rect]; UIBezierPath *p = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:(_bottomLeftRadius?UIRectCornerBottomLeft:0)|(_bottomRightRadius?UIRectCornerBottomRight:0)|(_topLeftR adius?UIRectCornerTopLeft:0)|(_topRightRadius?UIRectCornerTopRight:0) cornerRadii:CGSizeMake(_singleCornerRadius, 0.f)]; CGContextRef c = UIGraphicsGetCurrentContext(); CGContextAddPath(c, p.CGPath); CGContextClosePath(c); CGContextClip(c); CGContextAddRect(c, rect); CGContextSetFillColorWithColor(c, _bgColor.CGColor); CGContextFillPath(c); }Copy the code
This section describes how to transfer GPU operations to cpus to balance GPU and CPU operations.
Data source preloading
After the iOS 10, you can use, can use UITableViewDataSourcePrefetching agent method, the data can be preloaded
func tableView(tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { let needFetch = indexPaths.contains { $0.section >= self.layoutArray.count - 1 } if needFetch { // 1. Meet the conditions to make a page turn request}}Copy the code
Data source preprocessing
After the network requests the data, it preprocesses the data, putting the initialization logic of NSAttributeString and the data source logic processing in a cross-step thread.
If AutoLayout is not used, the frame of the subview can be calculated during data source preprocessing.
Optimize the cellForRow method
Move events such as the cell’s background color processing and event binding to the willDisplayCell. In the cellforRow method, no logic is done, just a simple assignment.
AutoLayout
If the cell uses an AutoLayout layout, there are two issues to be aware of:
-
1. The constraint conflict problem should be solved. This error is often reported in dynamic operation of constraint values.
To solve such problems, we can start from two aspects: 1. Analyze whether constraints are reasonable. 2. You can try changing the Priority of the constraint.
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600003b0cc80 DBRadiusView:0x7fb9d80b0e20.bottom == UIImageView:0x7fb9d80b59c0.bottom + 8>
Copy the code
- 2, to avoid
Loss of constraint
Problems, avoid incell
Repeated in the reuse processRemove the constraint
andAdditional constraints
Avoiding View Deletion
If message views are needed, avoid removing the view from the cell and use the Hidden property whenever possible.
Results contrast
Now that we’ve done these optimizations, let’s look at the Cartun distribution
The maximum holdup time ratio is 32.84ms/s. When the list is sliding, there is no high grade holdup, so a relatively ideal state is achieved.
Before and after video:
Before optimization: Youku link
After optimization: Youku link