返回首页

iOS Performance Optimization Series 03|Common Problems with iOS List Stuttering

List lagging is usually caused by the main thread taking on too much work that competes with the current frame during the scrolling process.

List lagging is the most common and most easily misjudged performance problem in iOS projects.

As soon as I see this situation and the list is not going smoothly, I will immediately say:

  • Is SwiftUI List too slow?
  • Is UICollectionView configured incorrectly?
  • Is this control inherently stuck?

These judgments are sometimes not entirely wrong, but they are often superficial. The real, more central question is usually:

In scrolling, an action that relies heavily on the main thread’s timely response, how much extra work does the system do at the same time?

Therefore, although UITableView, UICollectionView, and SwiftUI List are implemented in different ways, they often fall into very similar problems.

1. Lists are more likely to expose performance problems than many pages.

Because the list is a high-frequency, continuous scene that is sensitive to every frame.

As the user scrolls, the system needs to continuously complete these things:

  • Calculate layout
  • Prepare visible units
  • Reuse and recycling units
  • draw content
  • Respond to gestures

If the main thread is also asked to take on a lot of extra work at the same time, such as:

  • Picture decoding
  • Rich text assembly
  • JSON parsing
  • High cost Auto Layout calculations
  • Frequent status changes lead to full refresh

That lag is almost an inevitable result.

The reason why the list is so popular is that it appears to be mysterious on the surface, but in fact it is closer to it, which amplifies the pressure on the main thread very obviously.

2. The most common problem is that you do something you shouldn’t do at this moment while scrolling.

A common approach when optimizing is to only focus on the cell code length when optimizing lists. But in real projects, the reasons for list cards are often more like the following:

  • The image is not decoded until it is displayed
  • Text height is calculated repeatedly during scrolling
  • cell is reformatted and data converted every time it appears.
  • Too many parent layer state updates triggered when scrolling the list
  • A small change causes the entire list to be redrawn or the diff to be too expensive

The common features of these problems are: They are meant to be “should not be done at this moment of scrolling”.

So the most important idea for list optimization is:

  • What tasks can be done in advance?
  • Which jobs can be cached
  • What tasks can be postponed
  • Which updates can be localized

3. Pictures are often the culprit of list lags. On the surface, they look like downloads, but they are actually closer to decoding and size processing.

Many teams say “too many pictures” when they encounter list cards. Sometimes the direction of this sentence is right, but the reason is often wrong.

What really slows down scrolling is often:

  • Picture decoding
  • Picture zoom
  • Inappropriate size loading
  • Frequently trigger image processing on the main thread

That said, the scariest thing about the graphics problem is that it can easily insert costly work on the critical path of a roll.

Therefore, the core of image optimization in the list is usually not just caching, but:

  • Prepare the appropriate size in advance
  • Reduce the decoding pressure at the moment of display
  • Avoid heavy image processing when scrolling

4. Data processing often quietly drags down the scrolling experience.

This is more common than one might think.

For example, a list item needs to be displayed:

  • Time formatting
  • Amount formatting
  • Rich text combination
  • Tag mapping
  • Complex status copywriting

If these things are done temporarily during the cell configuration phase, the main thread will continue to eat this cost during scrolling.

The most troublesome part of this type of problem is:

  • Functionally completely correct
  • The single cost does not seem exaggerated
  • But in high-frequency scrolling, it will be magnified exponentially

Therefore, a very important principle for list performance optimization is: **Let the display layer try to consume the prepared display data instead of doing a lot of conversions while scrolling. **

5. If the status update method is wrong, the list will get stuck, and it is often mistaken for a layout problem.

Some list problems are not at all complicated by the cell, but also by the state update granularity being too coarse.

For example:

  • Refresh the entire list as soon as the search keyword changes
  • Like an item and the entire page status tree is rebuilt
  • A paginated result comes back and the entire list is recalculated

This type of problem is easily misdiagnosed as:

  • UI components are too slow
  • The layout system is not efficient

In fact, the real problem is often:

**A small business change triggered a UI update that was far larger than necessary. **

So when troubleshooting list lags, one thing I often ask is:

Which items should be affected by this status change? Why did it affect such a large area in the end?

6. What are the common problems of UITableView, UICollectionView, and SwiftUI List?

Although the implementation details of these three systems are very different, the high-frequency performance issues are actually very similar:

  • doing too much main thread work during scrolling
  • The list item shows that the data is prepared too late
  • Image and text processing are placed on the critical path
  • Refresh granularity is too large
  • Certain layouts or view hierarchies are too complex

In other words, their common problems are not:

**The interactive form of the list itself is particularly sensitive to the main thread timing and work allocation. **

Therefore, the same wrong design can cause similar stucks in three different list controls.

7. A troubleshooting sequence that is closer to actual combat

If I want to check the list lag problem today, I usually will not change the code first, but first judge in this order:

  1. Stuttering occurs when the first screen appears, when scrolling quickly, or when pagination occurs.
  2. Whether the current list item has pictures, rich text or complex layout.
  3. Whether a lot of real-time conversions are done before the cell is displayed.
  4. Whether a certain local state change triggered an excessively large-scale refresh.
  5. Whether there is synchronized decoding, scaling or recalculation during scrolling.

The value of this sequence is: First find out “what work is occupying the main thread with scrolling” instead of guessing the framework problem first.

8. Conclusion: The essence of list lag is usually that too much work is stuffed on the critical path that shouldn’t be stuffed.

To put it in shorter form, I would say:

The list is stuck, and the core is usually scrolling. In this high-frequency scenario, the main thread carries too many layout, decoding, conversion and excessive refresh costs at the same time.

So the most important things for list optimization are:

  • Put work in advance
  • Cache the results
  • Reduce refresh granularity
  • Take the extra burden off the critical path

If you do these four things right, the list experience will usually be more stable than simply adjusting a few parameters.

FAQ

读完之后,下一步看什么

如果还想继续了解,可以从下面几个方向接着读。

Related

继续阅读

这里整理了同分类、同标签或同类问题的文章。