Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do I efficiently update a UITableView with Animation?
    primarykey
    data
    text
    <p>My iPad app features a UITableView populated from a feed. Like most RSS readers, it displays a list of links to blog posts in reverse chronological order, with their titles and a summary of each post. The feed updates frequently, and is quite large, around 500 posts. I'm using <a href="http://bill.dudney.net/roller/objc/entry/libxml2_push_parsing" rel="nofollow noreferrer">libxml2 push parsing</a> to efficiently download and parse the feed in an NSOperation subclass, constructing entry objects and updating a database as I go. But then I need to update the UITableView with changes.</p> <p>So far, the app has been updating the UITableView for every post parsed, as it is parsed. The parser performs a selector on the main thread to do this work. But this leads to some serious lag for a couple of seconds if a lot of cells need to be updated. I can mitigate this by running the table update on a background thread, but it seems that this is <a href="https://stackoverflow.com/questions/4751499/how-important-is-it-to-use-performselectoronmainthreadwithobjectwaituntildone">not a good idea</a>. So now I'm trying to figure out how to update the table more efficiently on the main thread.</p> <p>I could just call <code>reloadData</code> when all the posts have been parsed, but it's not very user friendly: there's no animation to indicate that anything has changed, just a flash and the new data is there. I'd much rather have it animate to show that new posts are added and old posts removed. Existing posts that are not removed from the feed should be pushed down the table by the new posts appearing at the top.</p> <p>I know this is possible. <a href="http://www.phantomfish.com/byline.html" rel="nofollow noreferrer">Byline</a>, to give one example, does a beautiful job. Each post is added or removed from the UITableView one-at-a-time with no gaps showing the table background. All without making the UI in the least bit unresponsive. How is that done??</p> <p>My latest attempt is to update the table only after all the posts have been parsed (the parser is quite fast, so it's not much of a delay). It then loads the existing posts in an NSDictionary mapping their IDs to their indexes in the array used as the table data source. It then iterates over every object in the newly-parsed array of posts, adding NSIndexPath for each to arrays that are later passed to <code>-insertRowsAtIndexPaths:withRowAnimation:</code>, <code>-deleteRowsAtIndexPaths:withRowAnimation:</code>, and <code>-reloadRowsAtIndexPaths:withRowAnimation:</code> as appropriate to insert, remove, move, or update cells. For 500 posts, this takes around 4 seconds to update, with the UI completely unresponsive. That time is used almost exclusively for the UITableView animated updates; iterating over the two arrays of posts takes very little time.</p> <p>I then modified it so that those are updated <em>without animation</em>, and I have separate arrays to insert/delete/reload with animation only for row positions corresponding to currently-visible rows. This is better, but gaps appear as posts are removed and new ones added.</p> <p>Sorry this is so long-winded, but here's the upshot:</p> <p>How can I update a UITableView, with new cells pushed on, others pushed off, and still others moved from one position to another, with up to 500 cells in the UITableView (6-8 are visible at one time), and each animation happening in sequence, all while the UI remains completely responsive?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload