如何将NSArray的文件名添加到NSTableView? - 可可

时间:2012-02-18 23:48:50

标签: cocoa nsarray nstableview

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

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 个答案:

答案 0 :(得分:1)

有两种方法可以执行此操作:Cocoa Bindings使用NSArrayController或在对象中实施NSTableDataSource协议,并将该对象指定为表格视图datasource。< / p>

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

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource> 

您已经实现了所需的数据源方法,因此理论上一切都应该正常,但您可能没有将AppDelegate对象设置为表视图的datasource。您可以在代码中执行此操作:

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

或者,您可以通过将表格视图的datasource插座设置为AppDelegate实例,在Interface Builder中指定数据源。

但是,您遇到的主要问题是您正在为list ivar分配一个自动释放的对象,并且在表视图重新加载之前它已被释放。

您的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];
}