2008-10-14 4 views
22

J'essaye de sous-classer NSCell pour l'usage dans un NSTableView. La cellule que je veux créer est assez compliquée donc ce serait très utile si je pouvais la concevoir dans Interface Builder et ensuite charger le NSCell à partir d'une plume.Est-il possible de concevoir des sous-classes NSCell dans Interface Builder?

Est-ce possible? Comment fait-on ça?

+0

Maintenant que NSTableView prend en charge NSTableCellView, je me demande s'il existe une meilleure façon de prendre en charge tout ce qui concerne IB. – tofutim

Répondre

0

Je fais comme ça:

/* example of a silly way to load a UITableViewCell from a standalone nib */ 

+ (CEntryTableViewCell *)cell 
{ 
// TODO -- this is really silly. 
NSArray *theObjects = [[NSBundle mainBundle] loadNibNamed:@"EntryTableViewCell" owner:self options:NULL]; 
for (id theObject in theObjects) 
    if ([theObject isKindOfClass:self]) 
     return(theObject); 
NSAssert(NO, @"Could not find object of class CEntryTableViewCell in nib"); 
return(NULL); 
} 

Cependant, il est pas très efficace et si vous chargez beaucoup de données, il pourrait vous blesser. Bien sûr, vous devriez utiliser un reuseIdentifier qui devrait forcer ce code à ne s'exécuter qu'une poignée de fois par table.

+1

La question était pour Cocoa, pas Cocoa Touch – srgtuszy

5

Dans IB, démarrez un XIB vide. Maintenant, allez à la palette et faites glisser dans un UITableViewCell, double-cliquez pour afficher et éditer.

ne doit inclure qu'un seul UITableViewCell dans IB, ou vous ne pouvez pas définir un identificateur de réutilisation (par opposition à l'affichage d'un UIView dans IB comme classe UITableViewCell personnalisée)). Ensuite, vous pouvez ajouter des étiquettes ou ce que vous voulez dans la cellule, ainsi que définir l'identifiant de réutilisation ou définir n'importe quel indicateur de divulgation que vous pourriez aimer.

Pour utiliser, vous fournissez le code comme celui-ci dans le tableView: cellForRow: atIndexPath: Méthode:

YourCustomCellClass *cell = (YourCustomCellClass *)[tableView dequeueReusableCellWithIdentifier:<IDYouSetInXIBFile>]; 
if (cell == nil) 
{ 
     NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:<YourXIBName> owner:self options:nil]; 
    id firstObject = [topLevelObjects objectAtIndex:0]; 
    if ([ firstObject isKindOfClass:[UITableViewCell class]]) 
     cell = firstObject; 
    else cell = [topLevelObjects objectAtIndex:1]; 
} 

Si vous avez des étiquettes ou d'autres contrôles que vous souhaitez référencer dans votre code, les câbler en IB votre classe de cellules personnalisées - PAS le propriétaire du fichier, que vous n'avez jamais besoin de définir en utilisant le code ci-dessus (vous pouvez le laisser comme NSObject). Editer: Je note que vous cherchez vraiment une réponse NSCell, mais l'approche du code pour utiliser IB devrait être identique dans Cocoa avec le code Cocoa Touch que j'ai utilisé ci-dessus car loadNibNamed est un appel Cocoa standard.

+0

D'une certaine manière, je l'ai fait mal la première fois, mais vos instructions détaillées (le début) ont sauvé la journée. Merci! – JOM

+6

Vous avez le mauvais système d'exploitation ici. Ce n'est pas Cocoa Touch. – Domness

11

La question portait sur une sous-classe de NSCell; les autres réponses semblent faire autre chose, profitant probablement de UITableViewCell étant une vue.

NSCell n'est pas une vue. Tout en établissant une cellule personnalisée dans IB serait une chose utile à faire, je pense que la réponse est fondamentalement "non, ce n'est pas possible". Lorsque vous sous-classez NSCell, vous faites à peu près votre propre dessin. Il n'y a pas de sous-cellules de support, ou de mise en page automatique paramétrée (ala NSView's springs et struts), ce que je soupçonne ce que vous cherchez. Le seul inconvénient est que vous pouvez concevoir une sous-classe NSCell que a fait faire la mise en page des sous-éléments et fourni des paramètres pour définir ces sous-éléments et tous les paramètres modifiables. Ensuite, vous devrez écrire un plugin IB pour que cette cellule et l'inspecteur qui l'accompagne soient disponibles au moment du design dans IB. Cependant, cela est probablement plus difficile que d'écrire une petite application personnalisée qui fait plus ou moins la même chose. Mettez un NSCell dans un contrôle au milieu d'une fenêtre, et faites-vous une interface utilisateur pour peaufiner les paramètres qui vous intéressent. Les liaisons peuvent rendre cela assez simple pour positionner des choses (par exemple, lier une valeur x à un curseur). ne pas obtenir une manipulation directe des éléments bien sûr. Lorsque vous avez terminé, vous pouvez archiver votre cellule et charger l'archive à l'exécution dans votre application réelle, ou vous pouvez simplement vous déconnecter des propriétés et les définir dans le code de votre application.

2

Joar Wingfors a écrit un article pour Stepwise il y a quelques années sur un sujet connexe, Subviews in TableView Rows.

La technique principale consiste à créer un NSCell pouvant héberger un NSView. Si vous deviez le faire, vous pourriez alors concevoir une sous-classe NSView dans Interface Builder que vous pourriez intégrer n'importe où vous avez besoin de cette cellule spécifique.

Une autre possibilité, si vous pouvez cibler Leopard, est de voir si vous devez utiliser un NSTableView ou si vous pouvez utiliser un NSCollectionView. Les vues de collection traitent directement en termes de "vues d'articles" plutôt que de cellules. Elles sont donc beaucoup plus simples à concevoir dans Interface Builder.

7

Comme Ken dit, NSCells et NSViews sont différents, et vous ne pouvez disposer NSView hiérarchies dans NIB, non NSCells (qui n'ont pas de hiérarchie explicite).

D'autre part, il n'y a rien qui vous empêche d'avoir une hiérarchie de NSViews et en user pour attirer votre NSCell - vous pouvez les ajouter au sous-vue de la vue parent de votre cellule, dites-leur à afficher, et les retirer de la fenêtre et personne ne serait le plus sage.

Dans ce cas, l'utilisation d'un NIB fonctionnerait, bien que cela semble être une tonne de tracas. Typiquement, je viens de remplacer l'objet qui prend NSCells avec un objet personnalisé qui prend mon NSViews, mais cela signifie que vous devez écrire votre propre code de manipulation de la souris, ce qui est très délicat. D'autre part, mon approche vous permet de lier les valeurs des vues dans NIB, de sorte que vous n'avez pas à faire de travail supplémentaire, ce qui est cool.

-1

Ajoutez votre UITableViewCell à votre tableviewcontroller et déclarer une propriété IBOutlet:

@interface KuguTableViewController : UITableViewController { 
    IBOutlet UITableViewCell *customTypeCell; 
} 

@property (readonly) UITableViewCell *customTypeCell; 

... puis à cellForRowAtIndexPath vous pouvez simplement utiliser votre cellulaire et mettez-le à être réutilisé:

static NSString *CellIdentifier = @"CustomCell" 
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) 
     cell = customTypeCell; 
     cell.reuseIdentifier = CellIdentifier; 
+0

Vous avez le mauvais système d'exploitation ici. – Domness

+0

ne mérite pas moins. – evdude100

11

Certains Les réponses à ce sujet sont passées à côté du sujet parce qu'elles parlent de Cocoa Touch, alors que la question originale portait sur Cocoa - les 2 API sont assez différentes à cet égard et Cocoa Touch rend la tâche facile parce que UITableViewCell est av Voir sous-classe. Pour l'information, j'ai dû faire quelque chose de très similaire dans NSOutlineView récemment - ce qui est fondamentalement le même, mais un peu plus difficile sinon parce que vous devez gérer la divulgation/l'effondrement des niveaux . Si vous êtes intéressé par le code, je posté à ce sujet ici: http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-designed-in-ib/

HTH

+0

exactement ce que je cherchais –

1

J'ai trouvé quelques exemples intéressants que je ne comprends pas tout à fait, cependant.

Les 2 derniers exemples travaillent avec NSTableViewDataSource et NSTableViewDelegate. Je voudrais utiliser Bindings un ArrayController dans le InterfaceBuilder pour connecter d'autres éléments de l'interface utilisateur comme les champs de texte.

0

1) Créer NSViewControllerTableViewCell.h

2) Créer dans TableViewCell.h certaines procédures comme

-(void)setText:(NSString *)text image:(NSImage *)image 

3) En classe principale #import "TableViewCell.h"

4) Dans la classe principale dans -(NSView *)tableView:viewForTableColumn:row: write:

NSImage *img = //some image 
TableViewCell *cell = [[TableViewCell alloc] initWithWindowNibName:@"TableViewCell"]; 
cell.view.init; 
[cell setText:@"some text" image:img]; 
return cell; 

J'espère que cela aidera =)

0

Je veux fournir une approche plus moderne ici.

A partir de iOS 5, UITableView a une méthode

(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier

Une fois que vous avez enregistré votre NIB contenant votre cellule, il suffit d'utiliser

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier

pour obtenir une nouvelle cellule. Si une cellule est disponible pour être réutilisée, elle sera renvoyée, sinon une nouvelle cellule est créée automatiquement et, dans ce cas, cela signifie qu'elle est chargée à partir du fichier NIB.

Questions connexes