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

发布于 2025-01-07 16:02:38 字数 1276 浏览 4 评论 0原文

我需要帮助弄清楚如何将 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

I need help figuring out how to display the contents of an NSArray into a NSTableView. My NSArray is filled with (or at least I think it is) filenames from a directory. I use NSFileManager to get the names of files in a directory and then I load that info into a NSArray. But I can't figure out how to load the NSArray into the 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦过后 2025-01-14 16:02:38

有两种方法可以做到这一点: Cocoa 绑定 使用 NSArrayController 或通过实施 NSTableDataSource 对象中的协议并将该对象分配为表视图的数据源

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

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource> 

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

- (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 声明为属性并合成其访问器:

< strong>.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];
}

There are two ways to do this: Cocoa Bindings using NSArrayController or by implementing the NSTableDataSource protocol in an object and assigning that object as the table view's datasource.

It looks like you have already half-implemented the NSTableViewDataSource method. You need to add the protocol declaration to your interface to indicate that your AppDelegate object implements the protocol:

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource> 

You have already implemented the required datasource methods, so in theory everything should be working, but you possibly have not set your AppDelegate object as the table view's datasource. You can do this in code:

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

Alternatively, you can assign the datasource in Interface Builder by setting the table view's datasource outlet to your AppDelegate instance.

However, the main problem you have is that you are assigning an autoreleased object to your list ivar, and it is being released before the table view reloads.

Your listArray method is problematic. There is no reason for path and pathFinal to be instance variables. They are only used once, so should be locally scoped. In fact, since path is a constant, it should be declared separately:

//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];
}

A much better way to do this would be to declare list as a property and synthesize its accessors:

.h:

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

.m:

@implementation AppDelegate
@synthesize list;
...

You can then use the property and it handles the retain/release for you:

- (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];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文