In my iPhone app, I have three tabs laid out using a UITabBarController
. The first tab (that loads on app launch) uses local data to load, and is very fast.
The second tab, though, which downloads an XML file from the web and parses it, then displays all the data in a UITableView
, takes a long time to load over slower connections (EDGE, 3G). And, since I do call my parser inside viewDidLoad
, the app won't switch to my second tab until everything is done—this means it takes a while to load the tab sometimes, and it looks like the app's locked up.
I'd rather be able to have the user switch to that tab, have the view load immediately—even if empty, and then have the data downloaded/parsed/displayed. I have the network activity spinner spinning, so at least the user can know something's happening.
Here's my current viewDidLoad
:
// Load in the latest stories when the app is launched.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Loading news view");
articles = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:@"http://example.com/mobile-app/latest-news.xml"];
NSLog(@"About to parse URL: %@", url);
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser.delegate = self;
[parser parse];
}
I found this article, which shows how to run threads in the background, but I tried implementing that code and couldn't get the background thread to load the data back into my UITableView - the code was called, but how would I make sure the parsed articles are loaded back into my table view?
It turns out I needed to reload my UITableView after loading the data in a secondary thread, and that fixes everything!
Here's the final code in my secondary thread + viewDidLoad function:
-(void)initilizeNewsViewWithData {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Start the network activity spinner in the top status bar.
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
articles = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:@"http://example.com/mobile-app/latest-news.xml"];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser.delegate = self;
[parser parse];
[tblLatestNews reloadData]; // Need to refresh the table after we fill up the array again.
[pool release];
}
// Load in the latest news stories in a secondary thread.
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelectorInBackground:@selector(initilizeNewsViewWithData) withObject:nil];
}
I was reminded of refreshing the table view from this answer: UITableView not displaying parsed data