【问题标题】:Cocoa class not displaying data in NSWindow可可类不在 NSWindow 中显示数据
【发布时间】:2010-05-05 09:06:52
【问题描述】:

我有一个类控制一个窗口,另一个类控制同一个 xib 中的另一个窗口,但是,第二个窗口从不显示它应该显示的内容。

在第一个类中,我分配并初始化第二个类,然后将一些信息传递给它。在第二个类中,它在表格视图中显示该数据。
是的,在 .xib 中我已经正确设置了所有连接,我已经检查了四次。代码也是正确的,与连接相同,我已经检查了四次。

编辑:是的,数组中有数据,类是 NSObjects。

Edit2:我发现了问题。出于某种原因,数组中填充了内容,但它返回 0 作为计数。

编辑 9000:

代码如下:

答案.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

【问题讨论】:

  • 盲人很难回答有关代码的问题。请发布 IB 的最小测试用例和屏幕截图。
  • 这很简单。它是由您的程序中的错误引起的。您需要做的就是修复错误,您的程序将按预期运行。
  • 我已经发布了代码。 setUp 方法在不同的类中被调用,并且确实将数据放入数组中。
  • 用户、投票和文本字段是否应该是弱引用?为什么不retain他们?
  • 我试过了,没用。

标签: cocoa class nstableview


【解决方案1】:

您的代码中的问题很多。

一方面,-setUpWithVoteCount:User:Text: 中的比较是不正确的:

window.isVisible = YES

那应该是比较运算符,== 而不是赋值运算符=

其次,您错误地命名了您的 ivars 和方法。实例变量(实际上是任何类型的变量)应该以小写字母开头。这是为了将它们与类名区分开来。查看Apple coding guidelines

我还建议像text 这样的名称对于存储像NSArray 这样的集合的变量来说是一个坏名称。相反,您应该将其命名为 textItems 之类的名称,以便清楚地表明该变量代表一个集合而不是单个字符串。

此外,该类本身的名称也很糟糕。你称它为MSAnswerView 但它不是视图,它是某种类型的窗口控制器。至少叫它MSAnswerWindowController。最好将其设为NSWindowController 的子类,并使其File's Owner 在其自己的笔尖中。这是窗口控制器的标准模式。

你的方法 -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

【讨论】:

  • 没关系,我只是愚蠢,没有告诉前一个控制器显示窗口。非常感谢!!!!!!
猜你喜欢
  • 2011-06-23
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-10
  • 2016-01-15
  • 2011-10-26
  • 1970-01-01
相关资源
最近更新 更多