Reputation: 223
I've built an iOS 7 app using storyboards. Within my offersViewController I have a UIView and a UITableView. The UIView acts as a subview that displays a loading message while my feed is been parsed. Once complete the subview is removed and my parsed data is presented in my UITableView.
@interface OffersViewController ()
@end
@implementation OffersViewController
@synthesize loadingView;
MoreCobaltOffers *currentFeed;
AppDelegate *appDelegate;
- (void)viewDidAppear:(BOOL)animated
{
[self.tableView addSubview:loadingView];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Navigation"]];
CustomStringParser *customStringParser = [[CustomStringParser alloc] init];
// Download and parse XML data
RXMLElement *rxml = [RXMLElement elementFromXMLData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.myrssfeed.com"]]];
// Create an reference to AppDelegate
appDelegate = [[UIApplication sharedApplication] delegate];
// Create an array to store each feed
appDelegate.offersFeeds = [[NSMutableArray alloc] init];
// Loop Through XML Data
[rxml iterate:@"channel" usingBlock:^(RXMLElement *supportElement) {
[supportElement iterate:@"item" usingBlock:^(RXMLElement *repElement) {
// Assign element to string
NSString *title = [repElement child:@"title"].text;
NSString *subtitle = [repElement child:@"tagline"].text;
NSString *description = [repElement child:@"description"].text;
NSString *imageurl = [repElement child:@"image"].text;
NSString *address = [repElement child:@"address"].text;
// Assign element value to MoreCobalt.h propertys
currentFeed = [MoreCobaltOffers alloc];
currentFeed.title = title;
currentFeed.imageurl = imageurl;
currentFeed.addressline = address;
// DESCRIPTION FORMATTING
description = [customStringParser parseHTML:description];
description = [customStringParser parseLinesMultiple:description];
description = [customStringParser removeSocialSignifiers:description];
description = [customStringParser appendTermsOfUse:description];
currentFeed.description = description;
// SUBTITLE FORMATTING
subtitle = [customStringParser parseHTML:subtitle];
subtitle = [customStringParser parseLinesSingle:subtitle];
subtitle = [customStringParser removeSocialSignifiers:subtitle];
currentFeed.subtitle = subtitle;
// Add a new object to the feeds array
[[appDelegate offersFeeds] addObject:currentFeed];
}];
//Remove the loading screen
[loadingView removeFromSuperview];
//Show table data, if this is not here the table is empty.
[self.tableView reloadData];
}];
}
When I run the app the loading screen appears and then the table is displayed with data. If I navigate away from this view controller to another tab and then navigate back the table will flash. Not very good user experience.
The line of code responsible is [self.tableView reloadData];
. I need this in or table becomes empty. What am I doing wrong?
Upvotes: 0
Views: 809
Reputation: 13783
ViewWillAppear is called any time the view appears. In order for the table not to reload each time, move the code inside viewDidAppear.
For showing the loading view only one time move the parsing to another method like:
- (void)parseFeed {
[self.loadingIndicator startAnimating];
self.loadingIndicator.hidesWhenStopped = YES;
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Navigation"]];
CustomStringParser *customStringParser = [[CustomStringParser alloc] init];
// Download and parse XML data
RXMLElement *rxml = [RXMLElement elementFromXMLData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.morecobalt.co.uk/rss/?t=offers"]]];
// Create an reference to AppDelegate
appDelegate = [[UIApplication sharedApplication] delegate];
// Create an array to store each feed
appDelegate.offersFeeds = [[NSMutableArray alloc] init];
// Loop Through XML Data
[rxml iterate:@"channel" usingBlock:^(RXMLElement *supportElement) {
[supportElement iterate:@"item" usingBlock:^(RXMLElement *repElement) {
// Assign element to string
NSString *title = [repElement child:@"title"].text;
NSString *subtitle = [repElement child:@"tagline"].text;
NSString *description = [repElement child:@"description"].text;
NSString *imageurl = [repElement child:@"image"].text;
NSString *address = [repElement child:@"address"].text;
// Assign element value to MoreCobalt.h propertys
currentFeed = [MoreCobaltOffers alloc];
currentFeed.title = title;
currentFeed.imageurl = imageurl;
currentFeed.addressline = address;
// DESCRIPTION FORMATTING
description = [customStringParser parseHTML:description];
description = [customStringParser parseLinesMultiple:description];
description = [customStringParser removeSocialSignifiers:description];
description = [customStringParser appendTermsOfUse:description];
currentFeed.description = description;
// SUBTITLE FORMATTING
subtitle = [customStringParser parseHTML:subtitle];
subtitle = [customStringParser parseLinesSingle:subtitle];
subtitle = [customStringParser removeSocialSignifiers:subtitle];
currentFeed.subtitle = subtitle;
// Add a new object to the feeds array
[[appDelegate offersFeeds] addObject:currentFeed];
}];
[loadingView removeFromSuperview];
[self.loadingIndicator stopAnimating];
[self.tableView reloadData];
}];
[loadingView removeFromSuperview];
[self.loadingIndicator stopAnimating];
isFirstLoad = NO;
}
Declare a BOOL to check if it is first load and do this check:
-(void)viewDidAppear:(BOOL)animated {
if (isFirstLoad){
[self parseFeed];
}
[super viewDidAppear:animated];
}
Upvotes: 1
Reputation: 5654
Few things worth nothing:
You should extract all of that code for the parsing of your XML into another class. You should not be parsing data from XML inside of a view controller.
Right now you're running your network calls and parsing the XML data every time the view appears. What you might consider is only doing it when the view loads, thus running your code in viewDidLoad
Whenever you end up moving the code you might consider having a temporary local array and filling that with the XML return values, then using isEqualToArray
to compare it to your property of values to see if its different. If it is, reload the table and set the property anew, if not, don't.
Upvotes: 0