У меня есть один класс, который управляет одним окном и другим классом, который управляет другим окном в том же xib, однако, второе окно никогда не отображает то, что это должно.
В первом классе I выделений и init второй класс, затем передайте некоторую информацию ему. Во втором классе это отображает те данные в табличном представлении.
Да, в .xib у меня есть все соединения, настроенные правильно, я четыре раза проверил. Также код является правильным, то же с соединениями, я четыре раза проверил.
Править: и да, в массивах существуют данные, и классы являются NSObjects.
Edit2: Я отчасти нашел проблему. По некоторым причинам массив заполнен содержанием, но он возвращается 0 как количество.
Редактирование 9000:
Вот код:
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
Проблемы в вашем коде многочисленны.
Во-первых, сравнение в -setUpWithVoteCount:User:Text:
неверно:
window.isVisible = YES
Это должен быть оператор сравнения, ==
, а не оператор присваивания =
.
Во-вторых, вы неправильно называете свои ивары и методы. Переменные экземпляра (фактически, переменные любого типа) должны начинаться со строчной буквы. Это делается для того, чтобы отличить их от имен классов. Посмотрите Руководство по кодированию Apple.
Я бы также предположил, что имя типа text
- плохое имя для переменной, хранящей коллекцию типа NSArray
. Вместо этого следует назвать ее как-нибудь вроде textItems
, чтобы было ясно, что переменная представляет коллекцию, а не одну строку.
Кроме того, сам класс назван неудачно. Вы назвали его MSAnswerView
, но это не представление, а какой-то контроллер окна. По крайней мере, назовите его MSAnswerWindowController
. Еще лучше было бы сделать его подклассом NSWindowController
и сделать его File's Owner в собственном nib. Это стандартный шаблон для оконных контроллеров.
Ваш метод -setUpWithVoteCount:User:Text:
действительно должен быть инициализатором:
- initWithVoteCount:user:text:
Так будет понятно, для чего он нужен и что его следует вызывать один раз при создании объекта.
Основная проблема, однако, заключается в том, что вы не сохраняете значения, которые передаете в метод setup. Это означает, что если ни один объект не сохранит ссылку на них, они исчезнут в какой-то неопределенный момент в будущем. Если вы обратитесь к ним позже, то произойдет сбой или, по крайней мере, вы получите неверные данные, что и происходит.
Конечно, в этом случае вы также должны добавить метод -dealloc
, чтобы убедиться, что вы освободите объекты, когда закончите с ними.
Собрав все эти предложения вместе, ваш класс должен выглядеть примерно так:
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