Description générale:
Pour commencer avec ce qui fonctionne, j'ai un UITableView
qui a été placé sur une vue générée par Xcode en utilisant Interface Builder. Le propriétaire du fichier de la vue est défini sur une sous-classe générée par Xcode de UIViewController
. À cette sous-classe, j'ai ajouté des implémentations de travail de numberOfSectionsInTableView: tableView:numberOfRowsInSection:
et tableView:cellForRowAtIndexPath:
et dataSource
et delegate
de la vue Table sont connectés à cette classe via le propriétaire du fichier dans Interface Builder.
La configuration ci-dessus fonctionne sans problème. Le problème se produit lorsque je souhaite déplacer les implémentations dataSource
et delegate
- de cette vue tabulaire vers une classe distincte, probablement parce qu'il existe d'autres contrôles sur la vue en plus de la vue tabulaire et de moi. Je voudrais déplacer le code lié à la vue Table vers sa propre classe. Pour ce faire, j'essaie ce qui suit:
UITableViewController
dans XcodenumberOfSectionsInTableView:
, tableView:numberOfRowsInSection:
et tableView:cellForRowAtIndexPath:
à la nouvelle sous-classeUITableViewController
vers le niveau supérieur du XIB existant dans InterfaceBuilder, supprimez les UIView
/UITableView
qui sont créés automatiquement pour cette UITableViewController
, puis définissez la classe de UITableViewController
pour qu'elle corresponde à la nouvelle sous-classeUITableView
et dataSource
existantes de delegate
qui fonctionnaient précédemment et connectez-les aux nouvelles UITableViewController
Une fois terminé, je n'ai pas de UITableView
de travail. Je me retrouve avec l'un des trois résultats qui peuvent apparemment se produire au hasard:
UITableView
se charge, j'obtiens une erreur d'exécution indiquant que j'envoie tableView:cellForRowAtIndexPath:
à un objet qui ne le reconnaît pasUITableView
se charge, le projet pénètre dans le débogueur sans erreurUITableView
n'apparaît pasAvec un débogage et ayant créé un projet de base juste pour reproduire ce problème, je vois généralement la 3ème option ci-dessus (pas d'erreur mais pas de vue de table visible). J'ai ajouté quelques appels NSLog et j'ai constaté que bien que numberOfSectionsInTableView:
et numberOfRowsInSection:
sont tous deux appelés, cellForRowAtIndexPath:
n'est pas. Je suis convaincu que je manque quelque chose de vraiment simple et j'espérais que la réponse serait évidente pour quelqu'un avec plus d'expérience que moi. Si cela ne s'avère pas être une réponse facile, je serais heureux de mettre à jour avec du code ou un exemple de projet. Merci pour votre temps!
Suivez les étapes pour reproduire:
TableTest
TableTestViewController.xib
dans Interface Builder et faites glisser un UITableView
sur la surface de vue fournie.UITableView
et dataSource
- de delegate
au propriétaire du fichier, qui devrait déjà représenter la classe TableTestViewController
-. Sauvegardez vos modificationsTableTestViewController.m:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(@"Returning num sections");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(@"Returning num rows");
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"Trying to return cell");
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.text = @"Hello";
NSLog(@"Returning cell");
return cell;
}
Build and Go, et vous devriez voir le mot Hello
apparaître dans le UITableView
Maintenant, pour tenter de déplacer la logique de cette UITableView
vers une classe distincte, créez d'abord un nouveau fichier dans Xcode, en choisissant la sous-classe UITableViewController
et en appelant la classe TableTestTableViewController
TableTestViewController.m
et placez-le dans TableTestTableViewController.m
, en remplaçant l'implémentation par défaut de ces trois méthodes par la nôtre.TableTestViewController.xib
-, faites glisser un UITableViewController
dans la fenêtre principale de l'IB et supprimez le nouvel objet UITableView
qui l'accompagne automatiquementUITableViewController
sur TableTestTableViewController
dataSource
et delegate
des UITableView
existantes et fonctionnant précédemment et reconnectez les deux mêmes liaisons à la nouvelle TableTestTableViewController
que nous avons créée .UITableView
ne fonctionne plus correctement Solution: Avec un peu plus de dépannage et une assistance des iPhone Developer Forums , j'ai documenté une solution! La sous-classe principale UIViewController
du projet a besoin d'une sortie pointant vers l'instance UITableViewController
. Pour ce faire, ajoutez simplement ce qui suit à l'en-tête de la vue principale (TableTestViewController.h
):
#import "TableTestTableViewController.h"
et
IBOutlet TableTestTableViewController *myTableViewController;
Ensuite, dans Interface Builder, connectez la nouvelle prise de File's Owner à TableTestTableViewController
dans la fenêtre principale d'IB. Aucun changement n'est nécessaire dans la partie UI du XIB. Le simple fait d'avoir cette prise en place, même si aucun code utilisateur ne l'utilise directement, résout complètement le problème. Merci à ceux qui ont aidé et le mérite revient à BaldEagle sur les Forums des développeurs iPhone pour avoir trouvé la solution.
J'ai suivi vos étapes, recréé le projet et rencontré le même problème. En gros, vous y êtes presque. Il manque 2 choses (une fois corrigé ça marche):
Vous devez connecter le tableView
du TableTestTableViewController
au UITableView
que vous avez à l'écran. Comme je l'ai dit précédemment car ce n'est pas IBOutlet
, vous pouvez remplacer la propriété tableView
et la faire et IBOutlet
:
@interface TableTestTableViewController : UITableViewController {
UITableView *tableView;
}
@property (nonatomic, retain) IBOutlet UITableView *tableView;
La prochaine chose est d'ajouter une référence au TableTestTableViewController
et de la conserver dans le TableTestViewController
. Sinon, votre TableTestTableViewController
peut être libéré (après avoir chargé la plume sans rien y accrocher.) Et c'est pourquoi vous voyez les résultats erratiques, les plantages ou rien ne s'affiche. Pour ce faire, ajoutez:
@interface TableTestViewController : UIViewController {
TableTestTableViewController *tableViewController;
}
@property (nonatomic, retain) IBOutlet TableTestTableViewController *tableViewController;
et connectez-le dans l'Interface Builder à l'instance TableTestTableViewController
.
Avec ce qui précède, cela a bien fonctionné sur ma machine.
Je pense aussi qu'il serait bon de préciser la motivation derrière tout cela (au lieu d'utiliser simplement le UITableViewController
avec son propre UITableView
). Dans mon cas, il s'agissait d'utiliser d'autres vues que le UITableView
sur le même écran de contenu. Je peux donc ajouter d'autres UILabels
ou UIImages
sous UIView
et afficher le UITableView
en dessous ou au-dessus d'eux.
Je viens de passer de nombreuses heures à arracher mes cheveux pour essayer de comprendre pourquoi un UITableView
n'apparaîtrait pas quand je l'ai intégré dans une plume séparée au lieu de la plume principale. J'ai finalement trouvé votre discussion ci-dessus et j'ai réalisé que c'était parce que mon UITableViewController
n'était pas conservé! Apparemment, les propriétés de délégué et de source de données de UITableView
ne sont pas marquées "conserver" et donc ma plume était en cours de chargement mais le contrôleur était lancé ... Et en raison des merveilles de objective-c, j'ai eu non messages d'erreur du tout ... Je ne comprends toujours pas pourquoi il ne s'est pas bloqué. Je sais que j'ai déjà vu "un message envoyé au xxx" ... pourquoi ne m'en donnait-il pas un?!?
Je pense que la plupart des développeurs supposeraient que la structure qu'ils construisent dans un constructeur d'interface serait conservée dans un contexte plus large (la Nib) et non soumise à publication. Je suppose que je sais pourquoi ils font ça .. pour que l'iPhone puisse déposer et recharger des parties de la plume sur une mémoire faible. Mais l'homme, c'était difficile à comprendre.
Quelqu'un peut-il me dire où j'aurais dû lire ce comportement dans la documentation?
Aussi - sur le raccordement de la vue. Tout d'abord, si vous en faites glisser un depuis le générateur d'interface utilisateur, vous verrez qu'ils connectent la propriété view (qui est un IBOutlet
) à la vue de table. Il n'est pas nécessaire d'exposer le tableView
, qui semble être défini en interne. En fait, il ne semble même pas nécessaire de définir la vue sauf si vous voulez une notification viewDidLoad
. Je viens de rompre la connexion de vue entre mon uitableview
et uitableviewcontroller
(uniquement délégué et ensemble de sources de données) et cela fonctionne apparemment bien.
Oui pour une raison quelconque (veuillez ajouter si quelqu'un sait pourquoi ...) tableView
la propriété de UITableViewController
n'est pas exposée en tant que IBOutlet
même s'il s'agit d'une propriété publique. Ainsi, lorsque vous utilisez Interface Builder, vous ne pouvez pas voir cette propriété pour vous connecter à votre autre UITableView
. Ainsi, dans votre sous-classe, vous pouvez créer une propriété tableView
marquée comme IBOutlet
et la connecter.
Tout cela me semble hacky et une solution de contournement, mais cela semble être le seul moyen de séparer un UITableViewController's
UITableView
et le placer ailleurs dans la hiérarchie de l'interface utilisateur. Je suis tombé sur le même problème lorsque j'ai essayé de concevoir la vue où il y a d'autres choses que le UITableView
et c'est ainsi que je l'ai résolu ... Est-ce la bonne approche ???
J'ai pu faire ce travail. J'ai construit un tableau de bord vraiment sympa avec 4 TableViews et une vue Web avec vidéo. La clé est d'avoir les contrôleurs tableView et les IBOutlets séparés vers les autres contrôleurs tableview définis dans le contrôleur de vue. Dans UIB, il vous suffit de connecter les autres contrôleurs tableview au propriétaire du fichier du contrôleur de vue. Connectez ensuite les tables aux contrôleurs de vue correspondants pour la source de données et le délégué.