Actualiser un tableau depuis un fichier PLIST lui-même mis a jour depuis le Web
Bonjour tout le monde,
J'imagine qu'à première vue je vais me faire huer au vue du titre
Je vous explique, sur l'application en cours, je récupère via une page web PHP un fichier XML dont j'enregistre le contenu sur l'iPhone dans un fichier PLIST. Le fichier XML et formater de façon a correspondre au fichier PLIST.
De là , je parse le fichier PLIST et j'insère les données en tableau (UITableView). Jusque là tout va bien, j'utilise le même système que le l'article suivant : "Drill down table view with a detail view" ([url=http://"http://www.iphonesdkarticles.com/2009/03/drill-down-table-view-with-detail-view.html"]ici[/url]), mais au lieu d'avoir un seul TableView, j'en utilise 3 différents (juste pour personnaliser les cellules selon l'infos). Bref tout marche encore une fois.
Mon problème est que j'ai un formulaire qui envoi des données sur une page Web PHP que je récupère en mettant à jour le fichier PLIST mais le tableau refuse de se recharger sachant que le fichier PLIST se met correctement à jour (Je vérifie que celui-ci est à jour en regardant dedans).
Le plus simple est que je vous montre mon code car je sais pas si je suis clair là .
Fichier : SecretsAppDelegate.h
Fichier : SecretsAppDelegate.m
Ceci est mon troisième TableView qui récupère les informations
Mon fichier qui est censé rafraichir le tableau une fois l'ajout terminer
Après je sais pas s'il est possible d'actualiser les données sachant qu'elles se trouvent toutes dans un seul et même fichier. Mais perso, je pense que j'y arriverai pas même si tout était séparé en 3 fichiers.
Voilà , en espérant ne pas trop donner de fil à retordre :P
Guillaume
J'imagine qu'à première vue je vais me faire huer au vue du titre
Je vous explique, sur l'application en cours, je récupère via une page web PHP un fichier XML dont j'enregistre le contenu sur l'iPhone dans un fichier PLIST. Le fichier XML et formater de façon a correspondre au fichier PLIST.
De là , je parse le fichier PLIST et j'insère les données en tableau (UITableView). Jusque là tout va bien, j'utilise le même système que le l'article suivant : "Drill down table view with a detail view" ([url=http://"http://www.iphonesdkarticles.com/2009/03/drill-down-table-view-with-detail-view.html"]ici[/url]), mais au lieu d'avoir un seul TableView, j'en utilise 3 différents (juste pour personnaliser les cellules selon l'infos). Bref tout marche encore une fois.
Mon problème est que j'ai un formulaire qui envoi des données sur une page Web PHP que je récupère en mettant à jour le fichier PLIST mais le tableau refuse de se recharger sachant que le fichier PLIST se met correctement à jour (Je vérifie que celui-ci est à jour en regardant dedans).
Le plus simple est que je vous montre mon code car je sais pas si je suis clair là .
Fichier : SecretsAppDelegate.h
<br />#import <UIKit/UIKit.h><br /><br />@class CategoriesViewController;<br />@class MessagerieViewController;<br />@class CharteViewController;<br /><br />@interface SecretsAppDelegate : NSObject <UIApplicationDelegate> {<br /> IBOutlet UIWindow *window;<br /> IBOutlet UITabBarController *tabBarController;<br /> <br /> NSMutableDictionary *data;<br /> NSString *filePath;<br /> <br /> CategoriesViewController *categoriesViewController;<br /> MessagerieViewController *messagerieViewController;<br /> CharteViewController *charteViewController;<br />}<br /><br />@property (nonatomic, retain) IBOutlet UIWindow *window;<br />@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;<br /><br />@property (nonatomic, retain) NSMutableDictionary *data;<br />@property (nonatomic, retain) NSString *filePath;<br /><br />- (void)reloadAllDatas;<br /><br />@end<br />
Fichier : SecretsAppDelegate.m
<br />- (void)applicationDidFinishLaunching:(UIApplication *)application { <br /> tabBarController = [[UITabBarController alloc] init]; <br /> <br /> categoriesViewController = [[CategoriesViewController alloc] init]; <br /> UINavigationController *tableNavOneController = [[[UINavigationController alloc] initWithRootViewController:categoriesViewController] autorelease];<br /> [categoriesViewController release];<br /> [tableNavOneController setNavigationBarHidden:FALSE];<br /> <br /> messagerieViewController = [[MessagerieViewController alloc] init]; <br /> UINavigationController *tableNavTwoController = [[[UINavigationController alloc] initWithRootViewController:messagerieViewController] autorelease];<br /> [messagerieViewController release];<br /> [tableNavTwoController setNavigationBarHidden:FALSE];<br /> <br /> charteViewController = [[CharteViewController alloc] init]; <br /> UINavigationController *tableNavThreeController = [[[UINavigationController alloc] initWithRootViewController:charteViewController] autorelease];<br /> [charteViewController release];<br /> [tableNavThreeController setNavigationBarHidden:FALSE];<br /> <br /> tabBarController.viewControllers = [NSArray arrayWithObjects:tableNavOneController, tableNavTwoController, tableNavThreeController, nil];<br /> <br /> [self reloadAllDatas];<br /> <br /> [window addSubview:tabBarController.view];<br /> [window makeKeyAndVisible];<br />}<br /><br />- (void)reloadAllDatas {<br /> NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);<br /> NSString *documentsDirectory = [paths objectAtIndex:0];<br /> filePath = [documentsDirectory stringByAppendingPathComponent:@"monfichier.plist"];<br /> <br /> NSURL *url = [NSURL URLWithString:@"http://www.monlienweb.com/monfichier.php"];<br /> ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];<br /> [request start];<br /> <br /> NSURL *urltwo = [NSURL URLWithString:@"http://www.monlienweb.com/monfichier.xml"];<br /> ASIHTTPRequest *requesttwo = [[[ASIHTTPRequest alloc] initWithURL:urltwo] autorelease];<br /> [requesttwo setDownloadDestinationPath:filePath];<br /> [requesttwo start];<br /> <br /> NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];<br /> self.data = tempDict;<br /> [tempDict release];<br />}
Ceci est mon troisième TableView qui récupère les informations
<br />- (void)viewDidLoad {<br /> [super viewDidLoad];<br /> [self reloadAllData];<br />}<br /><br />- (void)reloadAllData {<br /> SecretsAppDelegate *appDelegate = (SecretsAppDelegate *)[[UIApplication sharedApplication] delegate];<br /> [(SecretsAppDelegate *)appDelegate reloadAllDatas];<br /> <br /> self.tableDataSource = nil;<br /> <br /> if(CurrentLevel == 0) {<br /> NSArray *tempArray = [[NSArray alloc] init];<br /> self.tableDataSource = tempArray;<br /> [tempArray release];<br /> <br /> self.tableDataSource = [appDelegate.data objectForKey:@"Rows"];<br /> <br /> [self.tableView reloadData];<br /> }<br />}<br />
Mon fichier qui est censé rafraichir le tableau une fois l'ajout terminer
<br />- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {<br /> NSLog(@"data : %@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);<br /> NSString *response = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];<br /> <br /> SecretsAppDelegate *appDelegate = (SecretsAppDelegate *)[[UIApplication sharedApplication] delegate];<br /> [(SecretsAppDelegate *)appDelegate reloadAllDatas];<br /> <br /> TopicsViewController *topicsViewController = [[TopicsViewController alloc]init];<br /> [topicsViewController.topicsTable reloadData];<br /> <br /> [self.navigationController dismissModalViewControllerAnimated:YES];<br />}<br />
Après je sais pas s'il est possible d'actualiser les données sachant qu'elles se trouvent toutes dans un seul et même fichier. Mais perso, je pense que j'y arriverai pas même si tout était séparé en 3 fichiers.
Voilà , en espérant ne pas trop donner de fil à retordre :P
Guillaume
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Oui !
A priori pourquoi ne pas stocker le plist dans des NSMutableArray, changer les NSMutableArray, et quand tu le désires, peut-être seulement en fin, recopier les NSMutableArray dans les plist ?
N'est-ce pas un problème de synchronisation (atends-tu bien que le chargement soit terminé pour faire reloadAllDatas) ?
Fais-tu bien aussi [tableView reloadData] sur les table view qui le nécessitent ?
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
le data attendu n'est pas forcément totalement acheminé. Il est plus prudent de faire un NSMutableData et d'y ajouter peu à peu les données reçues.
voir
Et là , la partie du fichier TopicsViewController.m qui est censé rafraà®chir les infos :
J'admet que je suis dessus depuis maintenant plusieurs jours, mais je ne comprend pas vraiment comment ré-actualiser le tout.
Guillaume
Cela veut dire sans doute que tu fais un test en mettant simplement "1" comme texte à réceptionner, ou à la rigueur "1" suivi de lettres.
Je vois plus loin
Tu crées ainsi une seconde instance de TopicsViewController, et la table topicsViewController.topicsTable ne doit pas être celle de ton interface ? Il faut s'arranger pour reprendre ici le topicsViewController déjà créé et dont la table est installée sur l'interface.
Pour ceux qui est de "topicsTable", il s'agit bien du tableau de TopicsViewController, j'ai bien penser a le relier depuis Interface Builder.
Je sais plus si je l'est dit, mais toutes mes informations se trouvent dans un seul et même fichier PLIST, je me demande si le problème viendrait pas de là , et que le mieux et que je sépare en 3 fichier.
Ah non, pas du tout . Ecrit comme cela tu crées une nouvelle instance, et la topicTable est en l'air.
Fais NSLog(@%@",topicsViewController.topicsTable) , tu devrais avoir (null) comme réponse ici.
Non, ce n'est pas la raison, cela complique sans doute et peut par conséquent être plus facilement source d'erreur, mais ce n'est pas une raison fondamentale.
Comment je dois procéder pour renvoyer une instance avant ouverture du formulaire j'imagine ?
Sinon, je viens de tomber sur cette article, ça pourrait m'aider à -t-on avis ?
http://www.oni-ecchi.info/blog/iphone/iphone-delegate.html
Oui c'est un bon début :
dans le .h, si ton topicsViewController est instancié dans IB
Faire la connection dans Interface Builder.
Après dans le code, il suffit de mettre d'une part
@synthesize topicsViewController
d'autre part; remplacer
par un simple
Bon, je suis absent 2 petites heures ... Bon courage.
Et prends au passage l'astuce du NSLog(@%@",unObjet) cela permet de vérifier plein de trucs à l'exécution ...
Mais je sais pas à quoi relier "topicsViewController" dans Interface Builder.
Ta table view, elle est installée dans le xib principal ou dans un xib secondaire ?
L'instance topicsViewController est dans le xib principal avec la connexion vers ce topic. EN aucun cas, il ne faut alors créer de TopicsViewController dans ton code : tu n'en créerais pas un second par erreur dans viewDidLoad ?
La partie qui parse le fichier PLIST
Ca c'est le code de TopicViewController.m
Le code de AddPostviewController.m exécuté une fois la connection terminer
Comme tu vois dans le fichier AddPostViewController.m, il ya ce code qui permet de remettre à jour le fichier PLIST avec les dernières informations, notamment celles envoyés par le formulaire via l'iPhone
Cette partie marche très bien, puisque le fichier se met correctement à jour, mais là je me demande si le problème ne viendrai pas de là en fait :
J'ai l'impression que "self.tableDataSource", ne se met pas a jour lui par contre. Je divague certainement, mais c'est ce qui me vient à l'esprit pour le moment.
Une dernière chose, je sais pas si ça parait important, mais le "style" du fichier PLIST :
NSLog(@%@",self.tableDataSource) cela donne quoi ?
La partie
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
self.tableDataSource = tempArray;
[tempArray release];
ne sert strictement à rien. Puisque plus loin tu fais pointer self.tableDataSource vers self.tableDataSource = [appDelegate.data objectForKey:@Rows];
La property tableDataSource est dans quel mode ?
"NSMutableArray *tableDataSource;"
"@property (nonatomic, retain) NSMutableArray *tableDataSource;"
Par contre, NSLog(@%@, topicsViewController.topicsTable); me renvoi toujours null"
TopicsViewController est une sous classe de UIViewController ou de UITableViewController ?
topicsTable est bien une property dans TopicsViewController ?
Le code de l'interface :
Sinon, si possible, je peut te montrer via iChat en partage écran, mon appli et tu verras par toi même ?
et topicsViewController est le datasource des deux table view ?
Si c'est le cas il doit avoir deux outlets vers chacune de ces tables, et faire un reloadData sur chacune d'elles.
Si ce n'est pas trop confidentiel, tu peux m'envoyer par MP ton code
Maintenant, tu me dis qu'il y a une autre table view, bon, sans doute dans la vue parente de cette vue modale. Mais si un topicsViewController pointe sur cette table view, il ne s'agit pas de l'instance que tu as dans la vue modale. La table view n'a donc pas reçu de reloadData, car c'est un autre couple (topicsViewController,topicsTable).
Anomalie au moins au niveau de la gestion mémoire
Je me disais à la limite, de séparé le contenu, un tableau pour chaque informations, avoir quelque chose de bien distinct. Ensuite, pour le formulaire, je supprime la fenêtre modale (qui pose bien des souchis ) et à la place, je met un uialertview avec un textfiel et un textview, au moment de l'ajout, j'ajoute une nouvelle entrée dans le tableau message et recharge la vue.
Les informations se mettront à jour au prochain démarrage de l'application, donc ce qui évite de toujours se connecter au Net pour si ou ça.
T'en penses quoi ?
J'en pense deux choses :
1) L'architecture de tes vues & controllers est effectivement très "mélangée".
Remettre les choses à plat en définissant un seul emplacement pour le model (les data), redéfinir exactement les rôles pour chacun des view controllers, prendre un papier, un crayon et faire un schéma ne peut que t'éclaircir les idées.
2) Ce que tu as fais là est probablement un premier galop d'essai qui t'a familiarisé avec pas mal de choses.
3) Bien penser aux concepts de la programmation objet : Différence entre classe et instance, schéma Model-View-Controller, ...
4) Vérifier le fonctionnement au fur et à mesure, parce que là tu avais déjà un beau "meuble" difficile à démêler ...
Donc oui, si tu as le temps, tu gagneras beaucoup à remettre tout cela à plat, en perdant peut-être une journée au départ, mais en regagnant ensuite en travaillant sur de bons principes.
Je suis d'accord avec toi, j'ai déjà commencer à mettre à plat ce que je souhaite et essayer de relier le tout sur papier.
Exact , à vrai dire j'ai commencer il y a pas plus de 15 jours. :P
Etant à l'origine développeur Web (PHP, MySQL, Zend, Javascript/Ajax, ...), je devrais pouvoir mieux m'organiser, quitte a créer des groupes de dossiers pour bien distinguer le tout.
Pourtant, j'ai vérifier au fur et a mesure, mais je crois que j'ai voulu aller trop vite. Je crois qu'avant de vouloir apprendre trop de chose à la fois, vaudrait approfondir mes bases et me "stabilisé"
Je recommencerai l'appli de toute façon et repartant avec un esprit clair et précis.
En tout cas, je te remercie vraiment du temps que tu as pris pour m'aider, je n'hésiterai pas à revenir si jamais j'ai besoin d'un coup de pouce, encore merci
Juste un dernier problème, l'appli marche très bien, mais quand je test sur le device et que je coupe le wifi pour tester en 3G, l'appli se lance, bloque et se ferme aussitôt !? Une idée de ce qui peut faire planter comme ça ?