Как добавить NSArray имен файлов в NSTableView? - какао - PullRequest
0 голосов
/ 19 февраля 2012

Мне нужна помощь, чтобы понять, как отобразить содержимое 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 Ответ

1 голос
/ 19 февраля 2012

Есть два способа сделать это: Привязки какао с использованием NSArrayController или путем реализации протокола NSTableDataSource в объекте и присвоения этого объекта как табличное представление datasource.

Похоже, вы уже наполовину реализовали метод NSTableViewDataSource. Вам нужно добавить объявление протокола в ваш интерфейс, чтобы указать, что ваш объект AppDelegate реализует протокол:

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource> 

Вы уже реализовали требуемые методы источника данных, поэтому в теории все должно работать, но вы, возможно, не установили свой объект AppDelegate в качестве табличного представления datasource. Вы можете сделать это в коде:

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

В качестве альтернативы, вы можете назначить источник данных в Интерфейсном Разработчике, установив выход datasource табличного представления для вашего AppDelegate экземпляра.

Однако основная проблема, с которой вы столкнулись, заключается в том, что вы присваиваете автоматически выпущенный объект своему list ивару, и он освобождается до перезагрузки табличного представления.

Ваш метод listArray проблематичен. path и pathFinal не являются переменными экземпляра. Они используются только один раз, поэтому должны быть локально ограничены. Фактически, поскольку 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];
}
...