UITableView performance optimization and lag problem
1. The most common use is cell reuse, registration reuse identifier
- If the cell is not reused, a new cell is recreated whenever a cell is displayed on the screen
- If there is a lot of data, it will accumulate a lot of cells. If you reuse a cell, create an ID for the cell
- Whenever a cell needs to be displayed, it will go to the buffer pool and look for a cell that can be recycled, if the cell is not re-created
2. Avoid cell re-layout
- Cell layout fills and other operations are time-consuming, and are typically created with a good layout
- If you can put the cell into a custom class individually, the layout is good when initialized
3. Calculate and Cache cell properties and contents in advance
- When we create a data source method for a cell, the compiler does not first create the cell and then set the cell's height
- Instead, first determine the height of each cell according to the content, after height determination, and then create the cell to be displayed, when scrolling, whenever the cell into the virtual will calculate the height of the pre-estimate height to tell the compiler, the compiler knows the height, immediately after the cell is created, then call the height of the specific calculation method, This can be a waste of time to calculate the cell outside the display.
4. Reduce the number of controls in the cell
- Try to make the cell layout roughly the same, different styles of cell can use the unused reuse identifier, the initialization of the Add control,
- Not applicable can be hidden first
5. Do not use Clearcolor, no background color, and do not set the opacity to 0
- Rendering takes a long time
6. Using Local Updates
- If you only update a group, use reloadsection for local updates
7. Load network data, download images, use asynchronous loading, and cache
8. Use less AddView to dynamically add view to cell
9. Load Cell,cell on Demand when scrolling quickly, load only the cells in the range
10. Do not implement a useless proxy method, TableView only adhere to two protocols
11. Cache Line Height: Estimatedheightforrow can not and heightforrow inside of the layoutifneed at the same time exist, both exist before there will be "channeling" bug. So my advice is: as long as it is fixed line high to write the estimated row height to reduce the number of row high calls to improve performance. If the dynamic line does not write the estimation method, use a high-line cache dictionary to reduce the number of calls to the code
With the above problem, we can solve a lag problem when we optimize the tableview.
In iOS apps, UITableView should be one of the most used views. IPod, clock, Calendar, Memo, Mail, weather, photos, phone, SMS, Safari, App Store, ITunes, Game Center ... It is visible in almost every application that comes with it, and it's important to see it.
However, when using third-party applications, they often encounter performance problems, and generally appear to compare cards when scrolling, especially when the table cell contains pictures.
In fact, as long as the targeted optimization, this problem will not be. Interested can see lazytableimages This official example of the program, although also to download pictures from the Internet and display, but scrolling without the slightest card.
Let's talk about my understanding of UITableView. However, because I am also a beginner, may be wrong or omitted some, so for reference only.
First, the principle of uitableview. If you are interested, you can take a look at "about Table view in ios-based applications".
UITableView is a subclass of Uiscrollview, so it can automatically respond to scrolling events (typically scrolling up and down).
It contains 0 to more UITableViewCell objects and each table cell displays its own content. When the new cell needs to be displayed, it calls the Tableview:cellforrowatindexpath: method to get or create a cell, and when it is not, it is freed. This shows that at the same time, only one screen of the cell object is needed, 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, foot, and cells. When locating a cell, you need 2 fields: in which section, and in the first line of the sections. This is expressed in Nsindexpath in the iOS SDK, and Uikit adds indexpathforrow:insection to it: This method of creation.
Other things such as editing are not mentioned, because it is not related to this article.
After the introduction of the principle, the next step is to optimize it.
Use an opaque view.
Opaque views can greatly increase the speed of rendering. Therefore, if it is not necessary, you can set the Opaque property of the table cell and its child views to Yes (the default value).
The exceptions include the background color, which should have an alpha value of 1 (for example, do not use Clearcolor), an image should have an alpha value of 1, or be opaque when drawing.
Do not create unnecessary table cells repeatedly.
As I said earlier, UITableView only needs a screen of UITableViewCell objects. So when the cell is not visible, you can cache it and continue to use it when you need it.
UITableView also provides this mechanism simply by setting a identifier:
1 Static @" XXX " ; 2 UITableViewCell *cell = [TableView dequeuereusablecellwithidentifier:cellidentifier]; 3 if (cell = = nil) {4 cell = [[[ UITableViewCell alloc] Initwithstyle: Uitableviewcellstyledefault Reuseidentifier:cellidentifier] autorelease]; 5 }
It is worth mentioning 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.
In addition, when adding a table cell, if you do not need an animation effect, it is best not to use the Insertrowsatindexpaths:withrowanimation: method, but instead call the Reloaddata method directly. Because the former invokes the Tableview:cellforrowatindexpath: method on all indexpaths, even if the cell does not need to be displayed (not known as a bug), it is possible to create a large number of extra cells. Errata: Just test this on the simulator, there is no such bug when debugging the real machine.
Reduce the number of views.
UITableViewCell includes views such as Textlabel, Detailtextlabel, and ImageView, and you can customize some of them in its contentview. However, view is a large object, and creating it consumes more resources and also affects rendering performance.
If your table cell contains pictures and a large number, using the default UITableViewCell can have a significant impact on performance. Oddly, using a custom view, rather than a predefined view, is significantly faster.
The best solution, of course, is to inherit UITableViewCell and draw it on its own drawrect:
1- (void) DrawRect: (cgrect) Rect2 {3 if(image)4 {5 [Image Drawatpoint:imagepoint];6Self.image =Nil;7}Else {8 [PlaceHolder Drawatpoint:imagepoint];9 }Ten [text Drawinrect:textrect withfont:font linebreakmode:uilinebreakmodetailtruncation]; One}
However, you will find that the cell becomes blue when the row is selected, and the contents are blocked. The simplest way is to set the cell's Selectionstyle property to Uitableviewcellselectionstylenone so it won't be highlighted.
You can also create a calayer, draw the content onto a layer, and then call 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, deformations and other effects, it will affect the drawing speed. Workaround refer to the pre-rendered image later.
Don't do extra drawing work.
When implementing DrawRect:, its rect parameter is the area that needs to be drawn, which is not required to be drawn outside this area.
In the example above, you can use Cgrectintersectsrect, cgrectintersection, or cgrectcontainsrect to determine if you need to draw an image and text, and then call the drawing method.
Pre-rendered images.
You will find that even if the above points are achieved, there will still be a brief pause when the new image appears. The solution is to draw it once in the bitmap context, export it to a UIImage object, and then draw it to the screen, with detailed instructions for accelerating the image display of the iOS device using pre-rendering.
Do not block the main thread.
When you do, your table view should be smooth enough to scroll, but you can still make users feel uncomfortable. The common phenomenon is that when updating data, the entire interface is stuck and does not respond to user requests at all.
This behavior occurs because the main thread executes a long-time function or method that cannot draw the screen and respond to user requests until it finishes executing. The most common of these is the network request, which usually takes a few seconds, and you should not let the user wait that long.
The workaround is to use multi-threading to let the child threads execute the functions or methods. There is also a knowledge that, when the number of download threads exceeds 2 o'clock, it can significantly affect the performance of the main thread. So when using ASIHTTPRequest, you can use a nsoperationqueue to maintain the download request and set its maxconcurrentoperationcount to 2. Nsurlrequest can be implemented with GCD, or using Nsurlconnection's Setdelegatequeue: method.
Of course, you can also increase the number of download threads to speed up download times when you don't need to respond to user requests:
1 -(voidif5;}} -(void5;}-(void2
In addition, automatic loading of updated data is also friendly to users, which reduces the time users wait to download. For example, if you load 50 messages at a time, you can load more information when you scroll to the bottom 10th:
-(void) TableView: (UITableView *) TableView Willdisplaycell: (UITableViewCell *) cell Forrowatindexpath: (Nsindexpath *) Indexpath {if (Count-indexpath.row < &&!updating) {updating = YES; [Self UPDATE]; }//the Update method gets the result, set updating to No
It is also important to note that when the picture is downloaded, if the cell is visible, you also need to update the image:
1Nsarray *indexpaths =[Self.tableview indexpathsforvisiblerows];2 for(Nsindexpath *visibleindexpathinchindexpaths) {3 if(Indexpath = =Visibleindexpath) { 4Mytableviewcell *cell = (Mytableviewcell *) [Self.tableview Cellforrowatindexpath:indexpath];5Cell.image =image;6[Cell Setneedsdisplayinrect:imagerect]; Break; 7 }8}//can also not traverse, directly and the tail and the comparison, see whether in the middle can.
Finally, the insertrowsatindexpaths:withrowanimation: method, inserting a new line needs to be executed on the main thread, and inserting many rows at a time (for example, 50 rows), which will block the main thread for long. and replaced by the Reloaddata method, the instant processing is done.
iOS Development--Project Combat summary &uitableview Performance optimization and lag problem