2012-02-18 2 views
0

Мне нужна помощь в определении того, как отображать содержимое NSArray в NSTableView. Мой NSArray заполнен (или, по крайней мере, я думаю, что это) именами файлов из каталога. Я использую NSFileManager для получения имен файлов в каталоге, а затем загружаю эту информацию в NSArray. Но я не могу понять, как загрузить NSArray в NSTableView.Как добавить NSArray имен файлов в NSTableView? - cocoa

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 Bindings использованием NSArrayController или путем реализации протокола NSTableDataSource в объекте и назначение этого объекта как табличный вид datasource.

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

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource> 

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

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

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

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

Ваш 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]; 
} 
+0

У меня возникли проблемы при получении этой работы. Это просто ничего не делает, и я не получаю ошибок в журнале. Когда я ввел протокол NSTableDataSource, он сказал, что он не найден и сказал мне изменить его на NSTableViewDataSource, я не знаю, если это проблема. И у меня есть таблица как источник данных в IB и делегат, но ничего не происходит. Он также говорит, что directoryContentsAtPath устарел. – drewsdunne

+0

Извините, это моя ошибка с именем протокола, это 'NSTableViewDataSource'. Вы не устанавливаете представление таблицы в качестве источника данных, вы устанавливаете объект «AppController» в качестве источника данных в виде таблицы. Подключите выход 'datasource' таблицы вида к экземпляру' AppController'. 'directoryContentsAtPath' *** *** устарел. Если вы посмотрите на документы, оно предложит вам вместо этого использовать 'contentsOfDirectoryAtPath: error:'. –

+0

Извините, я допустил ошибку, я неправильно сформулировал это. У меня был «источник данных» табличного представления, подключенный к «AppController». Но он ничего не показывает в таблице, и в нем говорится, что такой метод экземпляра 'contentOfDirectoryAtPath: error:' – drewsdunne

Смежные вопросы