Comment fonctionne [self.tableView reloadData] savoir quelles sont les données pour recharger?

StackOverflow https://stackoverflow.com/questions/2442395

Question

Il me dérange à la mort que mon viewcontroller, qui se trouve être un tableViewController, sait sans être dit que sa propriété qui est un NSArray ou un NSDictionary détient les données qui doivent être chargées dans la table pour l'affichage.

On dirait que je devrais dire explicitement quelque chose comme:

[self.tableView useData:self.MyArray];

Je veux avoir plus d'un tableau à l'intérieur de mon tableViewController et de basculer entre un et l'autre programme.

Je remarque que lorsqu'un tableViewController utilise un searchViewController, vous pouvez faire ceci:

if (tableView == self.searchDisplayController.searchResultsTableView) {

J'ai même pu faire ceci:

self.tableView =  self.searchDisplayController.searchResultsTableView;
[self.tableView reloadData];

Mais nulle part je peux trouver comment mettre self.tableView Retour à la principale source de données!

Était-ce utile?

La solution

D'accord, je comprends vos frustrations parce que la grande majorité du matériel pédagogique iPhone ne paient pas suffisamment d'attention à la conception globale de l'application. Ils font une Beeline pour l'interface de bonbons pour les yeux et ne payez que du bout des lèvres façon que l'application doit gérer les données même si les données de manipulation est tout l'objet de l'application en premier lieu!

Le matériel didactique ne passent pas assez de temps pour expliquer le motif de conception Model-View-Controller sur lequel l'ensemble de l'API iPhone / Cocoa est basée. Vous avoir du mal à comprendre quoi que ce soit parce que vous continuez à essayer de caser la fonctionnalité dans les mauvais objets sous la croyance erronée que la vue de l'interface utilisateur est au cœur du programme que le matériel pédagogique vous ont amenés à croire. En vertu de cette mauvaise compréhension, rien n'a de sens, pas même la documentation Apple.

Vous devez revenir en arrière et repenser. Il n'est pas la fonction d'une vue de déterminer les données à afficher et quand pour l'afficher. Il n'est pas la fonction du contrôleur de vue de la table pour détenir, gérer ou stocker les données de l'application. Ces fonctions appartiennent bien à l'objet de modèle de données (que vous avez peut-être jamais entendu parler.) Vous rencontrez des problèmes parce que vous essayez de diviser la tâche de modèle de données dans la vue et le contrôleur de vue étaient-ils ne font pas partie.

Apparemment, votre application ne dispose même pas d'un modèle de données parce que vous tenez les données de la table en tant que propriétés du contrôleur tableview. Bien que vous voyez souvent ce dans les exemples de tutoriel simplistes, il est une mauvaise conception qui va s'effondrer sous la complexité de tout, mais les applications les plus triviales.

Au lieu de cela, vos données doivent être stockées et gérées dans son propre objet personnalisé. Ceci est le modèle de données. Dans votre cas, il semble que vous avez des données réparties sur deux tableaux afin que vous créer un objet quelque chose de modèle de données comme ceci:

@interface MyDataModel : NSObject {
@protected
    NSArray *arrayOne;
    NSArray *arrayTwo;
@public
    NSArray *currentlyUsedArray;

}
@property(nonatomic, retain)  NSArray *currentlyUsedArray;

-(void) switchToArrayOne;
-(void) switchToArrayTwo;
-(void) toggleUsedArray;

@end

#import "MyDataModel.h"

@interface MyDataModel ()
@property(nonatomic, retain)  NSArray *arrayOne;
@property(nonatomic, retain)  NSArray *arrayTwo;

@end


@implementation MyDataModel

- (id) init{
    if (self=[super init]) {
        self.arrayOne=//... initialize array from some source
        self.arrayTwo=//... initialize array from some source
        self.currentlyUsedArray=self.arrayOne; //whatever default you want
    }
    return self;
}

-(void) switchToArrayOne{
    self.currentlyUsedArray=self.arrayOne;
}

-(void) switchToArrayTwo{
    self.currentlyUsedArray=self.arrayTwo;
}

- (void) toggleUsedArray{
    if (self.currentlyUsedArray==self.arrayOne) {
        self.currentlyUsedArray=self.arrayTwo;
    }else {
        self.currentlyUsedArray=self.arrayOne;
    }
}

(Notez que les données réelles est encapsulé et que d'autres objets ne peuvent accéder au currentlyUsedArray. Le modèle de données qui décide des données pour fournir basée sur l'état interne des données.)

Cet objet modèle de données devrait être dans un endroit accessible à tous. La meilleure méthode consiste à en faire un singleton, mais la méthode rapide et sale est de ce parc comme un attribut du délégué de l'application.

Donc, vous contrôleur tableView vous auriez une propriété:

MyDataModel *theDataModel;
@property (nonatomic, retain) MyDataModel *theDataModel;

puis dans la mise en œuvre

@synthesize theDataModel;

-(MyDataModel *) theDataModel; {
    if (theDataModel; !=nil) {
        return theDataModel; ;
    }
    id appDelegate=[[UIApplication sharedApplication] delegate];
    self.theDataModel=appDelegate.theDataModelProperty;
    return theDataModel;
}

Ensuite, dans votre méthode DataSource tableview:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    ...
    cell.textLabel.text=[self.theDataModel.currentlyUsedArray objectAtIndex:indexPath.row];
    return cell;
}

Si un événement ne importe où dans l'application vous oblige à passer des tableaux, vous appelez simplement l'objet modèle de données du délégué de l'application et de l'envoyer le message de réseau de commutation approprié .

id appDelegate=[[UIApplication sharedApplication] delegate];
[appDelegate.theDataModelProperty toggleUsedArray];

Maintenant toutes les opérations de données ultérieures, que ce soit dans ce point de vue de table ou d'une autre vue complètement différent, utiliseront les données forment le tableau approprié.

Pourquoi passer par tout ce mal? Il est modulaire d'applications. Vous pouvez facilement ajouter des vues différentes dont chacune affichent les données d'une manière différente, sans avoir à réécrire la gestion de vos données à chaque fois. Vous pouvez utiliser le modèle de données pour gérer les données qui seront affichées dans une table, dans une WebView ou sur la ligne de commande. Vous pouvez même déplacer facilement le modèle de données à une application tout à fait différente.

Cette modularité permet la gestion des grandes applications complexes beaucoup plus facile. Vous avez un seul objet qui manipule et contrôle les données. Vous n'avez pas à craindre que certaines erreurs mineures dans un segment de code rarement utilisé plantera l'application entière. Vous pouvez facilement ou plug-in vues les enlever facilement sans casser l'application.

Ceci est bien sûr un exemple trivial, mais il montre de bonnes pratiques.

Toutefois, vous pouvez demander, comment cela résout le problème de la tableview savoir quelles sont les données à charger et quand le charger? Simple, il ne fonctionne pas. Il est pas le travail du tableview savoir whà des données pour charger ou quand charger. Le modèle de données gère les données et ce-contrôleur gère tableview le quand. (Vous pouvez même avoir les notifications d'émission de modèle de données lorsqu'il est mis à jour par exemple pour une URL. Le contrôleur de vue peut vous inscrire à la notification et appelez reloadData chaque fois que les modifications du modèle de données.)

Par compartimenter sans pitié et l'encapsulation des fonctionnalités dans MVC, vous créez des applications complexes à partir de composants simples et réutilisables qui sont faciles à entretenir et debug.

Il est vraiment mauvais matériaux les plus pédagogiques ne payer que du bout des lèvres à ce concept tout à fait critique.

Autres conseils

Un contrôleur de vue de la table ne « connaît sans être dit » anything-- il n'a pas en soi une propriété comme vous mentionnez que les données proviennent de. Vous fournissez ces données, une cellule à la fois, généralement dans votre sous-classe vue du contrôleur.

En général votre point de vue la table objet contrôleur est à la fois délégué de la vue de la table et le délégué de la source de données de l'affichage du tableau. De la documentation d'Apple :

  

Un objet UITableView doit avoir un   délégué et d'une source de données. Suivant   la conception Model-View-Controller   motif, les médie de source de données   entre l'application de modèle de données   (Qui est, à son modèle d'objets) et le   vue de table; le délégué, de l'autre   main, gère l'apparence et   comportement de l'affichage du tableau. Les données   source et le délégué sont souvent (mais   pas nécessairement) le même objet, et   cet objet est souvent une coutume   sous-classe de UITableViewController.

Le point de vue de la table ne prend pas dans un tableau ou un dictionnaire et extraire des données de ce; il vous demande à votre source de données ce qui devrait ressembler à chaque cellule. Vous implémentez que cette méthode:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

Et quel que soit le contenu de retour dans une cellule que vous voulez pour la ligne que vous vous demande au sujet. Vous pouvez mettre la logique là-dedans pour mélanger / match / extraire les données où que vous voulez.

Pouvez-vous la confusion venir d'une soupe de code exemple peut-être que ne sait pas au sujet de ce qui se passe? Je recommande la construction d'une vue de table à partir de zéro pour voir comment cette works-- il est facile de le faire en ajoutant une nouvelle classe à votre projet, vous pouvez sélectionner une sous-classe de UITableViewController à l'intérieur XCode dans l'assistant « nouveau ». Il préremplir le fichier .m avec toutes les méthodes vides pertinentes, y compris ce qui précède.


EDIT: Ne pas modifier la table afficher votre contrôleur de vue est propriétaire lors d'une recherche. Vous confondez la référence de l'instance appelée « tableView », que votre contrôleur de vue est propriétaire, avec l'argument de la méthode déléguée tableView:cellForRowAtIndexPath:, qui est juste de passer pour vous dire qui vue de table demande un cellule. Lorsque vous avez une recherche à mettre en place de façon normale avec le même viewcontroller étant le délégué à la fois la table par défaut / le contenu et les résultats de la recherche, vous pourriez être appelée avec soit. voir ici pour la documentation sur cette .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top