Updater la tableView d'un UIViewController à partir d'une autre classe
Bonjour à tous !
Voici le premier message que je post sur ce forum qui m'a l'air fort plaisant ma foi !
Alors voilà : je suis en train de créer une application telle que Contacts, sauf que j'ai un petit problème. J'ai une subclass d'un UIViewController qui s'appelle CreateContactViewController (j'importe le UITableViewDelegate&DataSource), et jai un outlet pour ma tableView qui s'appelle..tableView !
Ensuite, dans cette classe, j'ai d'autres properties, et notamment des arrays qui servent de DataSource pour ma tableView. J'ai crée une subclass de UITableViewCell que j'ai nommée CreateContactCell, qui est la classe des cellules de ma tableView. Cette classe a en entre autres deux outlets : un Label, et un TextField (pour que l'utilisateur entre ses informations).
Ce que je veux faire, c'est que dès que l'utilisateur commence à entrer des données dans une cellule (= dès qu'il commence à écrire), une autre cellule apparaisse.
J'ai donc ajouté le UITextFieldDelegate à CreateContactCell pour être en mesure d'ajouter une cellule dès que l'utilisateur commence à éditer.
Voici le problème : dans les IBAction whatever qui réagissent aux évènements, je dois pouvoir ajouter les nouvelles cellules à ce moment là . Or, le problème est que je dois pouvoir accéder au DataModel conservé dans les properties de mon CreateContactViewController, sauf qu'avec les Class Methods, c'est impossible, et que si je crée une instance de CreateContactViewController, les properties n'aura pas de données, car c'est une nouvelle instance...
J'ai donc cherché sur internet, et là j'ai vu sur stackoverflow que je pouvais créer une property navigationController dans mon AppDelegate, et utiliser la property visibleViewController. J'ai donc fait comme cela :
AppDelegate.m :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.navigationController = (UINavigationController *)self.window.rootViewController;
return YES;
}
-(CreateContactViewController *)visibleViewController
{
CreateContactViewController *controller = nil;
if ([self.navigationController.visibleViewController isKindOfClass:[CreateContactViewController class]]) {
CreateContactViewController *controller = (CreateContactViewController *)self.navigationController.visibleViewController;
} else {
CreateContactViewController *controller = nil;
}
return controller;
}
CreateContactCell.m :
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(@editingBegan:);
[CreateContactViewController checkIfDeletingRowsIsNeededAtSection:self.indexPath.section]; // check if other blank cells are out there : if yes : needs to be deleted
if ([textField.text isEqualToString:@""]) {
self.blankCell = YES;
self.firstEdition = YES;
} else {
self.blankCell = NO;
self.firstEdition = NO;
}
}
- (IBAction)editingChanged:(UITextField *)sender
{
NSLog(@editingChanged:);
if (self.isBlankCell && self.isFirstEdition) {
self.blankCell = NO;
self.firstEdition = NO;
[CreateContactViewController insertRowAtSection:self.indexPath.section]; // call methode to add new cell and check if no other is blank
}
}
CreateContactViewController.m
+(void)insertRowAtSection:(NSInteger)section
{
CreateContactViewController *controller = nil;
id deletage = [[UIApplication sharedApplication] delegate];
if ([deletage performSelector:@selector(visibleViewController)]) {
controller = (CreateContactViewController *)[deletage visibleViewController];
}
NSLog(@%@", [[[[controller.arrayOfCellsWithTextValues.cells objectAtIndex:section] objectAtIndex:0] field] text]);
}
Le problème c'est que cette dernière ligne de code me renvoi (null).
Ainsi donc je vous demande, quelle est la meilleur approche pour pouvoir modifier le Data Model d'une autre classe pour ensuite pouvoir updater ma tableView en y ajoutant une cellule ?
Merci d'avoir pris le temps de me lire.
Hugo
Réponses
La bonne méthode est de passer l'objet nécessaire, c'est à dire lui transmettre un pointeur sur l'objet nécessaire, par exemple en déclarant une propriété dans le contrôleur destinataire.
Ta question sous-jacente est " Comment accéder au contrôleur 2 depuis le contrôleur 1 ?" et la réponse est qu'en général on n'y accède pas. En effet, si on respecte bien le MVC, les changements sont appliqués au modèle.
Reste donc une question: " comment savoir que le modèle a changé " ? Je ne vais pas trop m'étendre sur le sujet, évoqué maintes fois, mais en gros, voici les techniques par ordre de préférence:
1. Délégation
2. Key-Value Observing
3. Notifications
Comme explique par ceroce il faut essayer de respecter le modele MVC ou IHM
Pour le 2.Key-Value Observing
utilise cette fonction
keyPath est la string que tu envoi genre ca peut etre : creerContact , supprimerContact en fait ca depend ce que tu veux faire faire a la vue avec l'observeur
Bonjour,
Désolé de répondre si tardivement, mais j'ai eu les épreuves anticipées du bac donc pas eu le temps de programmer...mais merci pour vos réponses !
@Céroce : Vous voilà en gros je veux accéder à un viewController à partir d'une autre classe, mais le problème c'est que la seule manière de modifier une tableView est à partir du ViewController lui même et non pas du Model.
(et à @Am_Me) : Donc vous me proposez d'attendre de voir si le Model est modifier pour ensuite à l'interieur du Controller remarquer ce changement et faire des modifications de la View en conséquence ?
C'est bien ça ? Et donc pouvez-vous me donner un exemple d'implémentation de la méthode ci-dessus ?
Merci !
Dans ta fonction init :
le petit truc magique c'est NSKeyValueObservingOptionNew qui comme sont nom l'indique detecte les changements. Alors je sais pas si c'est du MVC Push ou Pull (Je dirais plus pull).
Dans ton observer
J'ai été gentil et encore (ce n'est peut etre pas la meilleur facon de faire qui sait :P ) ;D. Va faire un tour sur le Programme guide que te conseil Aligator.
Okay, donc j'ai lu l'intro du programming guide du KVO, et en gros le KVO dans mon cas :
Dès que on commence à remplir une Cell, j'incrémente une property quelconque (disons numberOfCellsNeeded). Je set ma TableViewController comme étant observer de ma property, et des que y'a un changement, je suis à même de modifier mon Data contenu dans une property de mon TableViewController et ainsi d'update ma tableView en conséquence ?
EDIT : autre petite question hors contexte mais qui me tracasse : quelle est la différence entre self.myProperty et _myProperty ?
Aucune si je ne dis pas de bêtises
Plop.
Une p'tite case sur le forum de présentation pour connaà®tre ton background ?
Si, une grosse bétise !
x = self.myProperty est l'équivalent de x = [self myProperty]
self.myProperty = x est l'équivalent de [self setMyProperty:x]
Or [self setMyProperty:] appelle donc la méthode setter de ta propriété
Tiens
Belle explications comme quoi s'était une grosse bêtise mais tant mieux
@Am_Me : Apparemment si !
@Larme : Ouai je vais poster un message de présentation dans la section appropriée, sinon tu as pu me voir sur les forums MacG
@AliGator : D'accord, bon j'ai pas tout compris en ce qui concerne les évènement de KVO, mais certes il est inutile d'écrire ses propres setter si au final c'est le même code que lorsque le compilateur le fait
Donc en gros dans le cas self.myProperty = x, on peut utiliser _myProperty = x, mais pas dans le cas x = self.myProperty, est-ce bien cela ?
Mais pourquoi lorsque le compilateur synthesize les properties, pourquoi utilise t-il _myProperty et non self.myProperty ? Est-ce une bonne pratique de programmation en Objective-C ?
pas compris la question.
Ceci dit ces questions sur propriété vs ivar etc c'est du grand classique on en a déjà parlé plusieurs fois sur les forums, je t'invite à faire une recherche parce que j'ai un peu la flemme de répéter mon explication détaillée de 3km et les liens vers la doc Apple :P
Ouai j'ai trouvé dans choses sur le forum mais tout le monde se contredit... Pourrais-tu me donner le lien de la doc Apple stp ?
Sinon qu'est ce qu'une variable d'instance ? Est-ce :
Parce que je cherche sur internet et les forums mais c'est juste pas clair..
qui mène (lien tout en bas) vers le Programming Guide bien plus complet "Programming with Objective-C" : Encapsulating Data
Okay merci