2010-05-04 4 views
1

J'ai une classe qui contrôle une fenêtre, et une autre classe qui contrôle une fenêtre différente dans le même xib, cependant, la deuxième fenêtre n'affiche jamais ce qu'elle devrait.Classe Cocoa ne pas afficher de données dans NSWindow

Dans la première classe je alloue et init la seconde classe, puis lui passe des informations. Dans la deuxième classe, il affiche ces données dans la vue tableau.
Oui, dans le .xib j'ai toutes les connexions correctement configurées, j'ai quadruple vérifié. Aussi le code est correct, même avec les connexions, j'ai quadruple vérifié.

Éditer: et oui, il y a des données dans les tableaux, et les classes sont des objets NSO.

Édition2: J'ai trouvé le problème. Pour une raison quelconque, le tableau est rempli de contenu, mais il retourne 0 comme un nombre.

Modifier 9000:

Voici le code:

Answer.h

#import <Cocoa/Cocoa.h> 
@interface MSAnswerView : NSObject { 
    IBOutlet NSWindow *window; 
    NSArray *User; 
    NSArray *Vote; 
    NSArray *Text; 
    IBOutlet NSTableView *view; 
    IBOutlet NSTableColumn *voteCount; 
    IBOutlet NSTableColumn *saidUser; 
    IBOutlet NSTextView *body; 
} 
-(void)setUpWithVoteCount:(NSArray *)array User:(NSArray *)user Text:(NSArray *)text; 

@property (nonatomic, retain) NSWindow *window; 
@property (nonatomic, retain) NSTableView *view; 
@property (nonatomic, retain) NSTableColumn *voteCount; 
@property (nonatomic, retain) NSTableColumn *saidUser; 
@property (nonatomic, retain) NSTextView *body; 
@end 

.m

#import "MSAnswerView.h" 
@implementation MSAnswerView 
@synthesize view; 
@synthesize voteCount; 
@synthesize saidUser; 
@synthesize body; 
@synthesize window; 
-(void)awakeFromNib 
{ 
    [view setTarget:self]; 
    [view setDoubleAction:@selector(bodydata)]; 
    [view reloadData]; 
} 
-(void)setUpWithVoteCount:(NSArray *)array User:(NSArray *)user Text:(NSArray *)text 
{ 
    Vote = array; 
    User = user; 
    Text = text; 
    if (window.isVisible = YES) { 
     [view reloadData]; 
     [view setNeedsDisplay]; 

    } 
} 
-(int)numberOfRowsInTableView:(NSTableView *)aTable 
{ 
    return [User count];; 
} 

-(id)tableView:(NSTableView *)aTable objectValueForTableColumn:(NSTableColumn *)aCol row:(int)aRow 
{ 
    if (aCol == voteCount) 
    { 
     return [Vote objectAtIndex:aRow]; 
    } 
    else if (aCol == saidUser) 
    { 
     return [User objectAtIndex:aRow]; 
    } 
    else 
    { 
     return nil; 
    } 


} 

-(void)bodydata 
{ 
    int index = [view selectedRow]; 
    [body setString:[Text objectAtIndex:index]]; 
} 

@end 
+2

Il est difficile répondre aux questions sur le code en aveugle. Veuillez poster un cas de test minimal et des captures d'écran d'IB. – outis

+1

C'est facile. C'est causé par un bug dans votre programme. Tout ce que vous devez faire est de corriger le bug et votre programme fonctionnera comme prévu. – JeremyP

+0

J'ai posté le code. La méthode setUp est appelée dans une classe différente et met les données dans les tableaux. –

Répondre

2

Les problèmes dans votre code sont nombreux.

D'une part, cette comparaison -setUpWithVoteCount:User:Text: est incorrect:

window.isVisible = YES 

Ce devrait être l'opérateur de comparaison, == pas l'opérateur d'affectation =.

Deuxièmement, vous nommez incorrectement vos ivars et vos méthodes. Les variables d'instance (en fait, les variables de tout type) doivent commencer par une lettre minuscule. C'est pour les distinguer des noms de classe. Découvrez le Apple coding guidelines.

Je suggère également qu'un nom comme text est un nom incorrect pour une variable qui stocke une collection comme un NSArray. Au lieu de cela, vous devriez le nommer quelque chose comme textItems donc il est clair que la variable représente une collection et pas une seule chaîne.

De plus, la classe elle-même est mal nommée. Vous l'avez appelé MSAnswerView mais ce n'est pas une vue, c'est un type de contrôleur de fenêtre. Appelez-le au moins MSAnswerWindowController. Mieux encore serait d'en faire une sous-classe de NSWindowController et en faire Propriétaire du fichier dans sa propre plume. C'est le modèle standard pour les contrôleurs de fenêtre.

Votre méthode -setUpWithVoteCount:User:Text: devrait vraiment être un initialiseur:

- initWithVoteCount:user:text: 

De cette façon, il est clair ce qu'il est et qu'il devrait être appelé une fois au moment de la création d'un objet. Le problème principal, cependant, est que vous ne retenez pas les valeurs que vous transmettez à votre méthode d'installation. Cela signifie que si aucun autre objet ne leur fait référence, ils partiront à un moment indéterminé dans le futur. Si vous y accédez plus tard, vous allez planter ou au moins recevoir de mauvaises données, ce qui est en train de se produire.

Bien sûr, vous devez également ajouter une méthode -dealloc dans ce cas pour vous assurer de libérer les objets lorsque vous en avez fini avec eux.

Mettre toutes ces suggestions ensemble, votre classe devrait vraiment regarder quelque chose comme ceci:

MSAnswerWindowController.h:

#import <Cocoa/Cocoa.h> 

//subclass of NSWindowController 
@interface MSAnswerWindowController : NSWindowController <NSTableViewDataSource> 
{ 
    //renamed ivars 
    NSArray *users; 
    NSArray *voteCounts; 
    NSArray *textItems; 
    IBOutlet NSTableView *view; 
    IBOutlet NSTableColumn *voteCount; 
    IBOutlet NSTableColumn *saidUser; 
    IBOutlet NSTextView *body; 
} 

//this is now an init method 
- (id)initWithVoteCounts:(NSArray *)someVoteCounts users:(NSArray *)someUsers textItems:(NSArray *)items; 

//accessors for the ivars 
@property (nonatomic, copy) NSArray* users; 
@property (nonatomic, copy) NSArray* voteCounts; 
@property (nonatomic, copy) NSArray* textItems; 

@property (nonatomic, retain) NSWindow *window; 
@property (nonatomic, retain) NSTableView *view; 
@property (nonatomic, retain) NSTableColumn *voteCount; 
@property (nonatomic, retain) NSTableColumn *saidUser; 
@property (nonatomic, retain) NSTextView *body; 
@end 

MSAnswerWindowController.m:

#import "MSAnswerWindowController.h" 

@implementation MSAnswerWindowController 

//implement the init method 
- (id)initWithVoteCounts:(NSArray*)someVoteCounts users:(NSArray*)someUsers textItems:(NSArray*)items 
{ 
    //this is an NSWindowController, so tell super to load the nib 
    self = [super initWithWindowNibName:@"MSAnswerWindow"]; 
    if(self) 
    { 
     //copy all the arrays that are passed in 
     //this means we hold a strong reference to them 
     users  = [someUsers copy]; 
     voteCounts = [someVoteCounts copy]; 
     textItems = [items copy]; 
    } 
    return self; 
} 

//make sure we deallocate the object when done 
- (void)dealloc 
{ 
    self.users  = nil; 
    self.voteCounts = nil; 
    self.textItems = nil; 
    [super dealloc]; 
} 

//this is called when the window first loads 
//we do initial window setup here 
- (void)windowDidLoad 
{ 
    [view setTarget:self]; 
    [view setDataSource:self]; 
    [view setDoubleAction:@selector(bodydata)]; 
} 

//this is called when the view controller is asked to show its window 
//we load the table here 
- (IBAction)showWindow:(id)sender 
{ 
    [super showWindow:sender]; 
    [view reloadData]; 
} 

- (NSInteger)numberOfRowsInTableView:(NSTableView*)aTable 
{ 
    return [users count]; 
} 

- (id)tableView:(NSTableView*)aTable objectValueForTableColumn:(NSTableColumn*)aCol row:(NSInteger)aRow 
{ 
    if (aCol == voteCount) 
    { 
     return [voteCounts objectAtIndex:aRow]; 
    } 
    else if (aCol == saidUser) 
    { 
     return [users objectAtIndex:aRow]; 
    } 
    return nil; 
} 

- (void)bodydata 
{ 
    NSInteger index = [view selectedRow]; 
    [body setString:[textItems objectAtIndex:index]]; 
} 

@synthesize users; 
@synthesize voteCounts; 
@synthesize textItems; 
@synthesize view; 
@synthesize voteCount; 
@synthesize saidUser; 
@synthesize body; 
@end 
+0

wow, merci !! Le seul problème que j'ai est le xib ne se charge pas ... –

+0

rien, j'étais juste stupide et ne pas dire au contrôleur précédent d'afficher la fenêtre. Merci beaucoup! –

Questions connexes