In iOS applications, UITableView is probably one of the most used views. It can be seen in almost all built-in applications, such as iPod, clock, calendar, memo, Mail, weather, photos, phone, SMS, Safari, App Store, iTunes, Game Center, etc., which shows its importance. However, when using third-party applications, performance issues are often encountered, generally manifested in slow scrolling, especially when the table cell contains images. In fact, as long as we optimize it in a targeted way, this problem will not exist. If you are interested, you can take a look at the official example program LazyTableImages. Although it also needs to download pictures from the Internet and display them, there is no lag when scrolling. Let me talk about my understanding of UITableView. However, since I am also a beginner, I may say something wrong or miss something, so it is only for reference. First, let's talk about the principle of UITableView. If you are interested, you can read "About Table Views in iOS-Based Applications". UITableView is a subclass of UIScrollView, so it can automatically respond to scroll events (usually scrolling up and down). It contains 0 or more UITableViewCell objects, and each table cell displays its own content. When a new cell needs to be displayed, the tableView:cellForRowAtIndexPath: method is called to obtain or create a cell; when it is not visible, it will be released. It can be seen that only one screen of cell objects needs to exist at the same time, and there is no need to create a cell for each row. In addition, UITableView can be divided into multiple sections, each of which can have its own head, footer, and cells. When locating a cell, two fields are required: which section it is in, and which row in this section. This is expressed in the iOS SDK using NSIndexPath, and UIKit adds the creation method indexPathForRow:inSection: for it. Other things such as editing will not be mentioned because they are not relevant to this article. After introducing the principle, let's start optimizing. Use an opaque view. Opaque views can greatly speed up rendering, so if not necessary, set the opaque property of the table cell and its subviews to YES (the default value). Special cases include background colors, which should have an alpha value of 1 (e.g., do not use clearColor); images should also have an alpha value of 1, or be set to opaque when drawing. Do not create unnecessary table cells repeatedly. As mentioned earlier, UITableView only needs one screen of UITableViewCell objects. Therefore, when the cell is not visible, it can be cached and continued to be used when needed. UITableView also provides this mechanism, you only need to simply set an identifier:
It is worth mentioning that when a cell is reused, the content drawn inside it will not be automatically cleared, so you may need to call the setNeedsDisplayInRect: or setNeedsDisplay method. In addition, when adding table cells, if you do not need animation effects, it is best not to use the insertRowsAtIndexPaths:withRowAnimation: method, but to call the reloadData method directly. Because the former will call the tableView:cellForRowAtIndexPath: method for all indexPaths, even if the cell does not need to be displayed (not sure if it is a bug), which may create a large number of redundant cells. Errata: This is only the case when testing on the simulator, and there is no such bug when debugging on a real machine. Reduce the number of views. UITableViewCell contains views such as textLabel, detailTextLabel, and imageView, and you can also customize some views and put them in its contentView. However, view is a large object, creating it will consume more resources and also affect rendering performance. If your table cells contain images, and there are many of them, using the default UITableViewCell will seriously affect performance. Strangely enough, using a custom view instead of a predefined view is significantly faster. Of course, the best solution is to inherit UITableViewCell and draw it yourself in its drawRect::
However, you will find that after selecting a row, the cell turns blue and the content is blocked. The easiest way is to set the cell's selectionStyle property to UITableViewCellSelectionStyleNone so that it will not be highlighted. You can also create a CALayer, draw the content onto the layer, and then call the addSublayer: method on the cell's contentView.layer. In this example, the layer does not significantly affect performance, but if the layer is transparent, or has rounded corners, deformation, etc., it will affect the drawing speed. For a solution, see the pre-rendered image below. Don't do unnecessary drawing work. When implementing drawRect:, its rect parameter is the area that needs to be drawn, and no drawing is required outside this area. For example, in the above example, you can use CGRectIntersectsRect, CGRectIntersection, or CGRectContainsRect to determine whether you need to draw the image and text, and then call the drawing method. Pre-rendered images. You will find that even if you do the above, there will still be a short pause when a new image appears. The solution is to draw it in the bitmap context first, export it as a UIImage object, and then draw it to the screen. For detailed instructions, see "Using pre-rendering to speed up image display on iOS devices". Don't block the main thread. After doing the first few points, your table view should scroll smoothly enough, but you may still make users feel unhappy. A common phenomenon is that when updating data, the entire interface is stuck and does not respond to user requests at all. The reason for this phenomenon is that the main thread executes a time-consuming function or method, and cannot draw the screen and respond to user requests before it is completed. The most common one is network requests, which usually take several seconds, and you should not let the user wait that long. The solution is to use multithreading and let the child threads execute these functions or methods. There is a trick here. When the number of download threads exceeds 2, the performance of the main thread will be significantly affected. Therefore, when using ASIHTTPRequest, you can use an NSOperationQueue to maintain the download request and set its maxConcurrentOperationCount to 2. NSURLRequest can be implemented with GCD, or use the setDelegateQueue: method of NSURLConnection. Of course, when you do not need to respond to user requests, you can also increase the number of download threads to speed up the download:
In addition, automatically loading updated data is also user-friendly, which reduces the time users wait for downloading. For example, if 50 pieces of information are loaded each time, more information can be loaded when scrolling to the last 10 pieces: - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { if (count - indexPath.row < 10 && !updating) { updating = YES; [self update]; } }// After the update method gets the result, set updating to NO Another thing to note is that after the image is downloaded, if the cell is visible, you also need to update the image:
*** Still the insertRowsAtIndexPaths:withRowAnimation: method mentioned above, inserting new rows needs to be executed in the main thread, and inserting many rows at a time (for example, 50 rows) will block the main thread for a long time. If you use the reloadData method instead, it will be processed instantly. |
<<: Google is developing an IoT version of Android to unify smart homes
>>: The development direction of Apple Watch from Disneyland
On August 8, the Qiantu K50 pure electric sports ...
"Users say they want this feature, why haven...
On March 20, the Sony PS4 console, which had been...
Internet products (especially new apps) are troub...
On December 15, BYD's B-class pioneer hunting...
Earlier this year, a senior traffic operator told...
Apple released iOS 17.0.3 today and closed the do...
For internet dogs, it is easy to organize an even...
Zhou Dawei's bodybuilding training course res...
There is actually no shortcut to planning an even...
The hydropower sector generated a record 4,370 TW...
Fans are the key to judging the value of a media ...
Recently, the topic "Auntie in Hangzhou, Zhe...