title: Refreshing XML data and updating a UITableView
body: <p>I'm developing an iPhone application which uses a TableView to display XML data. The XML data comes from an external resource and is parsed and put into an object for use as a table dataSource. The application uses a UITabBar and multiple ViewControllers all programmatically created and using the same dataSource.</p>
  
  <p>Everything is fine and dandy, but I'd like to implement a refresh button, so that a user can refresh the content (globally, so all the ViewControllers should be updated). The parser will query the XML again and create a new object. The problem I'm having is that I can't seem to repopulate the tableview with my new data. I get the updated data object. Actually updating the tableview is a problem though. I've tried to set <code>setDataSource</code> and call <code>reloadData</code>, but this results in a crash due to an unrecognised selector.</p>
  
  <p>The XML stuff is called from my AppDelegate and all the parsing logic is in Parser.m. The refresh function is called in RootViewController.m, which implements the UITableViewDataSource protocol:</p>
  
  <pre><code>- (void)refreshXMLFeed:(id)sender {
    NSArray *tableControllersData = [appDelegate getData];
    [self.tableView setDataSource: tableControllersData];
    [self.tableView reloadData];  
  }
  </code></pre>
  
  <p>How would I approach this issue? Should get the new data and reload the table view in the RootViewController as I have been trying to accomplish. Or should the data parsing be triggered in the AppDelegate and only the reloading of the TableView in RootViewController.</p>
  
  <p>If necessary I can update my question with the necessary code, I'm not sure which parts are relevant at this point.</p>
  
  <p>RootViewController.h:</p>
  
  <pre><code>#import &lt;UIKit/UIKit.h&gt;
  
  @interface RootViewController : UITableViewController {
    MyAppDelegate *appDelegate;
    NSArray *tableDataArray;
  }
  
  @property (nonatomic, retain) NSArray *tableDataArray;
  
  - (IBAction)refreshXMLFeed:(id)sender;
  - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil tableDataSource:(NSArray*)tableData;
  
  @end
  </code></pre>
  
  <p>RootViewController.m:</p>
  
  <pre><code>#import "CustomCell.h"
  #import "MyAppDelegate.h"
  #import "RootViewController.h"
  #import "DetailViewController.h"
  
  @implementation RootViewController
  @synthesize tableDataArray;
  
  - (void)viewDidLoad {
    [super viewDidLoad];
  }
  
  //Override the default initWithNibName method
  - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil tableDataSource:(NSArray*)tableData {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
      // Custom initialization
      tableDataArray = [tableData retain];   
    }
    return self;
  }
  
  -(void)viewWillAppear:(BOOL)animated {
    appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];    
    [super viewWillAppear:animated];
    //Set the colour of the navigationController and add buttons
    self.navigationController.navigationBar.tintColor = [UIColor blackColor];
  
    //Add the refresh button
    UIBarButtonItem* refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshXMLFeed:)];
    [self.navigationItem setLeftBarButtonItem:refreshButton animated:YES];
    [refreshButton release];  
  }
  
  #pragma mark Table
  
  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.tableDataArray count];
  }
  
  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CustomCellIdentifier = @"CustomCellIdentifier";
    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
    if (cell == nil) {
      NSArray *cellNib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
      for (id oneObject in cellNib) {
        if ([oneObject isKindOfClass:[CustomCell class]]) {
          cell = (CustomCell *)oneObject;
        }
      }
    }
  
    NSUInteger row = [indexPath row];
    NSDictionary *rowData = [self.tableDataArray objectAtIndex:row];
    cell.colorLabel.text = [rowData objectForKey:@"Type"];
    cell.nameLabel.text = [rowData objectForKey:@"Name"];
    UIImage *image = [UIImage imageNamed:[rowData objectForKey:@"Icon"]];
    cell.image = image;
    return cell;
  }
  
  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *selectedRow = [tableDataArray objectAtIndex:indexPath.row];
  
    DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:[NSBundle mainBundle]];
    detailViewController. selectedRow = selectedRow;
    [self.navigationController pushViewController:detailViewController animated:YES];
  
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] init];
    backButton.title = @"Back";
    self.navigationItem.backBarButtonItem = backButton;
    [backButton release];  
    [detailViewController release];
    detailViewController = nil;
  }
  
  #pragma mark Refresh
  
  - (void)refreshXMLFeed:(id)sender {
    NSArray *tableControllersData = [appDelegate getData];
    [self.tableView setDataSource: tableControllersData];
    [self.tableView reloadData];  
  }
  
  - (void)didReceiveMemoryWarning {
      // Releases the view if it doesn't have a superview.
      [super didReceiveMemoryWarning];
  
      // Release any cached data, images, etc that aren't in use.
  }
  
  - (void)viewDidUnload {
      // Release any retained subviews of the main view.
      // e.g. self.myOutlet = nil;
  }
  
  
  - (void)dealloc { 
      [super dealloc];
  }
  
  @end
  </code></pre>