How to optimize UITableView performance and uitableview
In iOS apps, UITableView should be the most frequently used and complex view. It can be seen in almost all built-in applications, and its importance can be seen. When you use UITableView, you will often encounter performance problems, which are generally manifested in comparison cards during scrolling, especially when table cells contain images. In fact, this problem will not happen if you optimize it in a targeted manner. If you are interested, you can refer to LazyTableImages, an official example program. Although you want to download images from the Internet and display them, they are not stuck during scrolling. First, let's talk about the principle of UITableView. If you are interested, please refer to "About Table Views in iOS-Based Applications". UITableView is a subclass of UIScrollView. Therefore, it can automatically respond to rolling events (generally upstream and downstream scrolling ). It contains 0 to multiple UITableViewCell objects, and each table cell displays its own content. When a new cell needs to be displayed, tableView: cellForRowAtIndexPath: is called to obtain or create a cell. If it is not visible, it is released. It can be seen that at the same time, you only need to have a cell object on the screen, and you do not need to create a cell for each row. In addition, UITableView can be divided into multiple sections. Each section can have its own head, foot, and cells. When locating a cell, two fields are required: the section in which the cell is located and the row in which the cell is located. This is expressed in the iOS SDK using NSIndexPath. UIKit adds indexPathForRow: inSection: This creation method to it. Other content, such as editing, will not be mentioned because it is irrelevant to this article. After introducing the principles, we will start to optimize them. Use an opaque view. An opaque view can greatly increase the rendering speed. Therefore, if not necessary, you can set the opaque attribute of table cell and its subviews to YES (default ). The special case includes the background color. Its alpha value should be 1 (for example, do not use clearColor), the alpha value of the image should also be 1, or it should be set to opacity when drawing. Do not create unnecessary table cells again. As mentioned above, UITableView only needs a UITableViewCell object on the screen. Therefore, when the cell is invisible, it can be cached and used as needed. UITableView also provides this mechanism. You only need to set an identifier: static NSString * CellIdentifier = @ "xxx"; UITableViewCell * cell = [tableView metadata: CellIdentifier]; if (cell = nil) {cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: CellIdentifier] autorelease];} It is worth noting that when the cell is reused, the content drawn inside it is not automatically cleared, so you may need to call the setNeedsDisplayInRect: Or setNeedsDisplay method. Reduce the number of views. You can also customize UITableViewCell. Each Cell can contain multiple sub-views, such as Label and ImageView. You can also customize some views and put them in its contentView. It should be noted that a view is a large object, which consumes a lot of memory and affects the rendering effect. If your table cell contains a large number of images, using the default UITableViewCell will greatly affect the performance. The strange thing is that using a custom view, rather than a pre-defined view, is obviously faster. Of course, the best solution is to inherit UITableViewCell and draw it in its drawRect:-(void) drawRect :( CGRect) rect {if (image) {[image drawAtPoint: imagePoint]; self. image = nil;} else {[placeHolder drawAtPoint: imagePoint];} [text drawInRect: textRect withFont: font lineBreakMode: blank];} then, you will find the selected row, the cell becomes blue, and the content is blocked. The simplest way is to set the cell's selectionStyle attribute to UITableViewCellSelectionStyleNone, so that it will not be highlighted. In addition, you can create CALayer, draw the content to the layer, and then call addSublayer: Method on the contentView. layer of the cell. In this example, the layer does not significantly affect the performance, but if the layer is transparent, or has a rounded corner, deformation, and other effects, the rendering speed will be affected. For the solution, see the pre-rendered image. Do not do unnecessary painting. When implementation of drawRect:, its rect parameter is the area to be drawn, which does not need to be drawn outside of this area. For example, in the above example, you can use CGRectIntersectsRect, CGRectIntersection, or CGRectContainsRect to determine whether image and text need to be drawn, and then call the painting method. Pre-rendered image. You will find that even if you have done the above, there will still be a short pause when new images appear. The solution is to first draw it in bitmap context, export it to a UIImage object, and then draw it to the screen, for details, see image display for iOS devices accelerated by pre-rendering. Do not block the main thread. After the first few points, your table view should be smooth enough to scroll, but you may still make users feel uncomfortable. A common phenomenon is that when updating data, the entire interface does not change and does not respond to user requests at all. The reason for this is that the main thread executes a function or method that takes a long time. Before execution, the screen cannot be drawn and the user request cannot be responded. The most common one is the network request, which usually takes several seconds, and you should not let the user wait so long. The solution is to use multiple threads to allow sub-threads to execute these functions or methods. There is another learning here. When the number of download threads exceeds 2, it will significantly affect the performance of the main thread. Therefore, when using ASIHTTPRequest, you can use an NSOperationQueue to maintain the download request and set its maxConcurrentOperationCount to 2. The NSURLRequest can be implemented with GCD, or the setDelegateQueue of NSURLConnection is used: method. 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 speed:-(void) scrollViewDidEndDragging :( UIScrollView *) scrollView willDecelerate :( BOOL) decelerate {if (! Decelerate) {queue. maxConcurrentOperationCount = 5; }}- (void) scrollViewDidEndDecelerating :( UIScrollView *) scrollView {queue. maxConcurrentOperationCount = 5;}-(void) scrollViewWillBeginDragging :( UIScrollView *) scrollView {queue. maxConcurrentOperationCount = 2;} In addition, it is user-friendly to automatically load and update data, which reduces the waiting time for users to download. For example, if 50 pieces of information are loaded each time, more information can be loaded when the last 10th pieces are rolled:-(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. Note that after the image is downloaded, if the cell is visible, you also need to update the image: NSArray * indexPaths = [self. tableView indexPathsForVisibleRows]; for (NSIndexPath * visibleIndexPath in indexPaths) {if (indexPath = visibleIndexPath) {MyTableViewCell * cell = (MyTableViewCell *) [self. tableView cellForRowAtIndexPath: indexPath]; cell. image = image; [cell setNeedsDispla YInRect: imageRect]; break;} // you can directly compare it with the header and tail to see if it is in the middle.Finally, the insertRowsAtIndexPaths: withRowAnimation: method mentioned above. To insert a new line, it must be executed in the main thread. If many lines are inserted at a time (for example, 50 rows), the main thread will be blocked for a long time. The reloadData method is replaced by the reloadData method.
Reprinted for reference only. The copyright belongs to the original author.
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.