【问题标题】:How to add an NSArray of filenames to a NSTableView? - cocoa如何将文件名的 NSArray 添加到 NSTableView? - 可可
【发布时间】:2012-02-18 23:48:50
【问题描述】:

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

【问题讨论】:

    标签: cocoa nsarray nstableview


    【解决方案1】:

    有两种方法可以做到这一点:Cocoa Bindings 使用 NSArrayController 或通过在对象中实现 NSTableDataSource 协议并将该对象分配为表视图的 datasource

    看起来您已经实现了一半的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];
    }
    

    【讨论】:

    • 我无法让它工作。它只是没有做任何事情,我在日志中没有收到任何错误。当我放入NSTableDataSource协议时,它说找不到并告诉我将其更改为NSTableViewDataSource,我不知道是不是这个问题。我将表设置为 IB 和委托中的数据源,但仍然没有发生任何事情。它还说 directoryContentsAtPath 已被弃用。
    • 对不起,这是我的协议名称错误,它是NSTableViewDataSource。您没有将表视图设置为数据源,而是将AppController 对象设置为表视图的数据源。将表视图的datasource 出口连接到AppController 实例。 directoryContentsAtPath 已弃用。如果您查看文档,它会告诉您改用contentsOfDirectoryAtPath:error:,所以这样做。
    • 对不起,我弄错了,我用错了。我确实将表格视图的datasource 连接到AppController。但它仍然没有在表格中显示任何内容,并且表示没有contentsOfDirectoryAtPath:error: 的此类实例方法
    • 使用the docs。您需要阅读文档并正确使用方法。
    • 我完全按照他们说的做,但现在它说没有contentsOfDirectoryAtPath:error: 的方法,它一直在崩溃。我想在来这里之前先看文档
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 2012-01-04
    相关资源
    最近更新 更多