返回首页

SwiftUI Series 08|Common pitfalls of SwiftUI List: refresh, delete, jump and performance

The real difficulty with List is that once data identity, status updates, and interaction behaviors are entangled, it is easy to cause problems together.

List is one of the controls in SwiftUI that is easiest to “look easy to write” and also easiest to get into trouble in real business.

Because many simple examples work well:

  • Data can be displayed as soon as it is thrown in
  • Pull-down refresh can also be accessed
  • Delete, jump, and partition seem to have ready capabilities

But once it starts to appear in the project:

  • Pagination
  • Search
  • Status linkage after deletion
  • Jump to details and return
  • Picture loading

The problem of List will gradually be exposed.

1. The root cause of many List problems is that “data identity” is not thought through clearly.

Many behaviors of SwiftUI are strongly related to identity. If the list data “looks the same” but the identity is unstable, it will easily appear later:

  • Bounces when refreshing
  • Weird animation when deleting
  • The scroll position is abnormal after returning to the list
  • The content of a certain row is refreshed incorrectly

So the most basic and most underestimated thing about List is:

  • Is the identity of each item stable?
  • Is this identity still trustworthy when refreshing, paging, and searching?

Many lists of “metaphysical bugs”, the final root cause is here.

2. Refreshing and paging often mess up the list status.

Because refreshing and paging are essentially modifying the “current list collection”, and collection changes will directly affect:

  • cell reuse relationship
  • scroll position
  • Current loading state
  • Switching between empty state and content state

If these relationships are not clarified, it is easy for:

  • The list will flash when you pull down to refresh.
  • Paginate back and recalculate the entire list
  • Old results overwrite new content

So the real difficulty with List is often:

  • Which states should be retained when refreshing?
  • Which states should be added when paging? -Whether there will be concurrent conflicts between requests of the same type

3. Deletion operations are often not as simple as “deleting an element”

On the surface, deletion just removes an element from the array. But in real lists, deletion often affects these things at the same time:

  • Current display collection
  • Empty state judgment
  • selected state
  • Jump state
  • Backend sync status

If you just “delete first and then talk”, it is easy to:

  • The deletion was successful, but the details page still points to the old object
  • When deletion fails, the list and server status are inconsistent
  • The animation is fine, but the data source rollback logic is confusing

This shows that the real difficulty in deletion is:

  • Who owns the data source?
  • Is the deletion an optimistic update or waiting for confirmation from the server?
  • How to close the navigation status after deletion?

4. Jumping is easy to get entangled with List and cause problems.

It is common to regard lists and jumps as independent functions, but in real projects they are very closely related.

Typical questions include:

  • Delete the current item after clicking into the details, and the return to the list status is incorrect.
  • After the list is refreshed, the original selected path will become invalid.
  • The search results jump to details and then return, and the list status is reset.

The nature of these problems is usually:

  • List data status
  • Selected item status
  • Navigation path status

are not treated as the same set of problems.

5. Performance problems are particularly easy to explode in List

Because the list magnifies many small problems.

For example:

  • item view hierarchy is too deep
  • Image loading and decoding too late
  • Text and data conversion is done in the display stage
  • Refresh granularity is too large

These costs may be bearable on ordinary pages, but in high-frequency scrolling scenarios like List, it can easily lead to frame drops and flickering.

So there are many List performance issues, and it is particularly sensitive to data identity, refresh range and display timing.

6. A more stable idea: first treat List as “state projection” instead of “container for data”

A common situation is that when writing a list, the default in mind is:

  • I have a set of data
  • Put in List

A more stable idea in real projects is:

  • What is the current page status?
  • Which batch of list items should this set of states be projected into?
  • Which list items have stable identities
  • Which user actions will change this set of states

Once you think of List as a state projection rather than a simple container, many questions start to become clear:

  • Give priority to identity
  • Delete, refresh, and paging cannot be viewed separately
  • The jump state should also be considered together

7. Conclusion: The real difficulty of List is that “identity, status, and interaction” can easily get entangled together.

To put it in shorter form, I would say:

List in SwiftUI The really difficult part is that once the interactions of data identity, page status and deletion/refresh/jump are intertwined, if any boundary is not established, problems will be exposed together.

Therefore, if you want to use List stably, the key is to first:

  • item identity
  • List status
  • Status flow after interaction

Straighten these three things out.

FAQ

读完之后,下一步看什么

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

Related

继续阅读

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