Je développe une application iPhone qui utilise TableView pour afficher des données XML. Les données XML proviennent d'une ressource externe et sont analysées et placées dans un objet à utiliser comme table dataSource. L'application utilise un UITabBar et plusieurs ViewControllers tous créés par programmation et utilisant la même source de données.Actualisation des données XML et mise à jour d'UITableView
Tout va bien et dandy, mais je voudrais implémenter un bouton d'actualisation, afin qu'un utilisateur puisse actualiser le contenu (globalement, donc tous les ViewControllers devraient être mis à jour). L'analyseur réexécutera le XML et créera un nouvel objet. Le problème que j'ai est que je ne peux pas sembler repeupler la tableview avec mes nouvelles données. Je reçois l'objet de données mis à jour. En fait, la mise à jour de la tableview est un problème. J'ai essayé de définir setDataSource
et d'appeler reloadData
, mais cela entraîne un blocage dû à un sélecteur non reconnu.
Le contenu XML est appelé à partir de mon AppDelegate et toute la logique d'analyse est dans Parser.m. La fonction de rafraîchissement est appelé à RootViewController.m, qui met en œuvre le protocole UITableViewDataSource:
- (void)refreshXMLFeed:(id)sender {
NSArray *tableControllersData = [appDelegate getData];
[self.tableView setDataSource: tableControllersData];
[self.tableView reloadData];
}
Comment pourrais-je aborder cette question? Devrait obtenir les nouvelles données et recharger la vue de table dans le RootViewController comme j'ai essayé d'accomplir. Ou l'analyse des données doit-elle être déclenchée dans AppDelegate et uniquement le rechargement de TableView dans RootViewController.
Si nécessaire, je peux mettre à jour ma question avec le code nécessaire, je ne sais pas quelles parties sont pertinentes à ce stade.
RootViewController.h:
#import <UIKit/UIKit.h>
@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
RootViewController.m:
#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
Merci pour la réponse. Les deux méthodes requises sont implémentées dans RootViewController - J'ai mis à jour la question initiale avec du code. Les données de dataSource sont un NSArray et alimentées par une méthode
initWithNibName
substituée. Donc je ne suis pas sûr que cela soit lié à des méthodes non implémentées. – menschLa source de données d'une vue de table * ne peut pas * être un NSArray car NSArray n'implémente pas le protocole UITableViewDataSource. Si vous avez implémenté les méthodes requises dans RootViewController, définissez l'instance RootViewController (ou self si elle se trouve à l'intérieur de RootViewController) en tant que source de données de la vue table. Votre problème n'a rien à voir avec initWithNibName. Le problème est que vous ne comprenez pas MVC. La source de données est un délégué - pas un conteneur de données. Le délégué doit accéder au conteneur de données (un NSArray dans votre cas) afin de renvoyer le nombre de lignes/sections et les cellules de tableau corrects. –
Désolé de mélanger la terminologie, le NSArray est en effet le conteneur de données et non le dataSource (c'est une source de données, cependant, d'où le mixage). RootViewController implémente les méthodes du protocole UITableViewDataSource et constitue la source de données appropriée pour TableView. Je suppose que ma question dans ce cas est comment nourrir un conteneur de données mis à jour NSArray et mettre à jour le TableView en conséquence. – mensch