2012-02-18 57 views
0

我需要帮助搞清楚如何显示一个NSArray的内容为NSTableView的。我的NSArray充满了(或者至少我认为它是)来自目录的文件名。我使用NSFileManager获取目录中文件的名称,然后将该信息加载到NSArray中。但我无法弄清楚如何将NSArray加载到NSTableView中。如何添加文件名到NSTableView的的一个NSArray? - 可可

AppDelegate.h

#import <Cocoa/Cocoa.h> 

@interface AppDelegate : NSObject <NSApplicationDelegate> { 
IBOutlet NSTableView *tableView; 

NSArray *list; 
IBOutlet NSTextField *text; 

NSFileManager *manager; 
NSString *path; 
NSString *pathFinal; 
} 

@property (assign) IBOutlet NSWindow *window; 

- (IBAction)listArray:(id)sender; 

@end 

AppDelegate.m

#import "AppDelegate.h" 

@implementation AppDelegate 

@synthesize window = _window; 

- (int)numberOfRowsInTableView:(NSTableView *)tableView 
{ 
    return [list count]; 
} 

- (id)tableView:(NSTableView *)tableView 
objectValueForTableColumn:(NSTableColumn *)tableColumn 
     row:(int)row 
{ 
    return [list objectAtIndex:row]; 
} 

- (IBAction)listArray:(id)sender { 
    path = @"~/Library/Application Support/minecraft/bin/"; 
    pathFinal = [path stringByExpandingTildeInPath]; 
    list = [manager directoryContentsAtPath:pathFinal]; 

    [tableView reloadData]; 
} 

- (void)dealloc 
{ 
    [super dealloc]; 
} 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 

} 

@end 

回答

1

有两种方法可以做到这一点:使用Cocoa BindingsNSArrayController通过实现在对象的NSTableDataSource协议和分配该对象作为桌子视图的datasource

看起来你已经一半实现了NSTableViewDataSource方法。您需要将协议声明添加到您的接口,用来表明您AppDelegate对象实现了协议:

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource> 

您已经实现了所需数据源的方法,所以理论上一切都应该是工作,但你可能没有设置您AppDelegate对象表视图的datasource。您可以在代码中做到这一点:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    [tableView setDatasource:self]; 
} 

或者,您也可以通过表视图的datasource出口设置为您AppDelegate实例分配在Interface Builder中的数据源。

但是,您遇到的主要问题是您将自动释放对象分配给您的0123arivar,并且在表视图重新加载之前它将被释放。

listArray方法是有问题的。没有理由对pathpathFinal是实例变量。他们只使用一次,所以应该在本地范围内。事实上,自path是恒定的,应当另行申报:

//this should go in the top of your .m file, after the #import directives 
static NSString* minecraftPath = @"~/Library/Application Support/minecraft/bin/"; 

- (IBAction)listArray:(id)sender 
{ 
    NSString* path = [minecraftPath stringByExpandingTildeInPath]; 

    //you want to hang onto the array that is returned here, so you must retain it 
    //however, if you don't release the existing value, it will be leaked 
    [list release]; 
    list = nil; 
    list = [[manager directoryContentsAtPath:pathFinal] retain]; 
    [tableView reloadData]; 
} 

- (void)dealloc 
{ 
    //because you retained it, you must release it 
    [list release]; 
    [super dealloc]; 
} 

一个更好的方式来做到这将是宣布list作为属性和合成及其访问:

.H:

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource> { 
... 
} 
... 
@property (retain) NSArray* list; 
... 

.M:

@implementation AppDelegate 
@synthesize list; 
... 

然后,您可以使用属性,并将其处理保留/释放你:

- (IBAction)listArray:(id)sender 
{ 
    NSString* path = [minecraftPath stringByExpandingTildeInPath]; 

    //you've set the property to use retain, so the synthesized accessor does that for you 
    self.list = [manager directoryContentsAtPath:pathFinal]; 
    [tableView reloadData]; 
} 

- (void)dealloc 
{ 
    //you still need to release when done 
    self.list = nil; 
    [super dealloc]; 
} 
+0

我遇到了麻烦这项工作。它只是没有做任何事情,我在日志中没有遇到任何错误。当我放入NSTableDataSource协议时,它说它没有找到,并告诉我将其更改为NSTableViewDataSource,我不知道是否是这个问题。我把表格设置为IB和委托人的数据源,但没有发生任何事情。它还说,directoryContentsAtPath已被弃用。 – drewsdunne 2012-02-19 18:51:44

+0

对不起,这是我的协议名称错误,它是'NSTableViewDataSource'。您不要将表视图设置为数据源,您将'AppController'对象设置为表视图的数据源。将表视图的'datasource'插座连接到'AppController'实例。 'directoryContentsAtPath' ***被***弃用。如果你看看文档,它会告诉你使用'contentsOfDirectoryAtPath:error:'来代替,所以这样做。 – 2012-02-20 03:48:25

+0

对不起,我犯了一个错误,我误解了这一点。我确实将表视图的'datasource'连接到'AppController'。但它仍然没有在表格中显示任何内容,并且表示没有'contentsOfDirectoryAtPath这样的实例方法:错误:' – drewsdunne 2012-02-20 04:34:30