TableView Optimized performance

Source: Internet
Author: User

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-almost all of your own apps can see it, and it's important.
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.

  1. 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.
  2. 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:
    static NSString *CellIdentifier = @"xxx"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; }
    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.
  3. to reduce the number of views. The
    UITableViewCell contains 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 greatly affect performance. Oddly, using a custom view, rather than a predefined view, is significantly faster.
    Of course, the best solution is to inherit UITableViewCell and draw it on its own drawrect:
     -(void) DrawRect: (cgrect) Rect {if (image) {[ Image Drawatpoint:imagepoint]; Self.image = nil; } else {[PlaceHolder drawatpoint:imagepoint];} [Text Drawinrect:textrect Withfont:font linebreakmode:uilinebreakmodetailtruncation];  
    However, you will find that when you select a row, the cell becomes blue 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.
  4. 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.
  5. 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.
  6. 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:
    - (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, 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 < 10 && !updating) { updating = YES; [self update]; } }// update方法获取到结果后,设置updating为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:
    NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];for (NSIndexPath *visibleIndexPath in indexPaths) { if (indexPath == visibleIndexPath) { MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath]; cell.image = image; [cell setNeedsDisplayInRect:imageRect]; break; } }// 也可不遍历,直接与头尾相比较,看是否在中间即可。
    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 replace it with the Reloaddata method, the moment is done.

TableView Optimized performance

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.