【问题标题】:Setting up NSTableView with NSMutableArray of custom classes as data source使用自定义类的 NSMutableArray 作为数据源设置 NSTableView
【发布时间】:2011-04-04 02:56:19
【问题描述】:

好的,所以我正在学习 Objective-C 和 Cocoa 中的编程,并且在我正在处理的项目中遇到了一个问题。所以在我的代码中,我有一个自定义类的对象的 NSMutableArray(源)。每个对象都有一个 NSString 名称。我正在尝试获取一个表格视图,以按每个对象的名称显示源中的所有对象。

我有一个遵循 NSTableViewDataSource 协议的应用委托类,这意味着有一个 objectValueForTableColumn 方法和一个 numberOfRowsInTableView 方法。

在 numberOfRowsInTableView 中,我只有一个返回 [sources count];声明,它工作正常。

在 objectValueForTableColumn 中,我返回了 [[sources objectAtIndex: rowIndex] name];,但没有显示任何内容。

我已经添加了很多NSLog语句进行调试,我想我知道问题是什么,但我不知道为什么,或者如何解决它。

所以,在objectValueForTableColumn 中,源数组为 nil。在内部,numberOfRowsInTableView,源是活动的,并且该方法工作正常。现在,这两种方法都运行了很多次,并且每次都在 numberOfRowsInTableView 中激活源,但在 objectValueForTableColumn 中为 nil。

我将objectValueForTableColumn 中的return 语句替换为return @"Test string.";,它在表格视图中显示了正确的行数。正因为如此,我知道表格视图设置正确,除了我在来源方面遇到的问题。

我不明白为什么来源在一种方法中有效,而在另一种方法中无效。我也没有找到让我的表格视图正常工作的解决方案。任何帮助或见解将不胜感激。

谢谢, 亚历克斯

编辑:

- (void) loadFromFile
{
NSString *filePath = @"/Users/alex/opt/Wallify.plist";
NSFileManager *filemgr = [NSFileManager defaultManager];

if ([filemgr fileExistsAtPath: filePath])
{
    NSData *data = [[NSData new] initWithContentsOfFile: filePath];
    NSLog(@"Loaded data from file.");


    self.sources = [NSKeyedUnarchiver unarchiveObjectWithData: data];
    [data release];

    for ( ATImageSource *i in sources)
    {
        NSLog(@"retaining i");
        [i retain];
    }



    [sources retain];


    NSLog(@"&imgsrc: %p", sources);
    NSLog(@"imgsrc: %@", sources);
    NSLog(@"Name: %@",[[sources objectAtIndex: 0] name]);

}
else
{
    //  Saved settings file does not exist
    //  Load defaults

    self.sources = [[NSMutableArray alloc] initWithArray: nil];
    [self.sources retain];

    // new code to setup testfoldersrc
    ATFolderSource *f = [ATFolderSource new];
    f.name = @"Documents";
    f.source = @"/Users/alex/Documents/";
    f.localPath = @"/Users/alex/Documents/";
    f.type = @"f";

    [f populateArrayFromLocalPath];

    [self.sources addObject: f];
    [f release];

    // new code to setup testrsssrc
    ATRSSSource *r = [ATRSSSource new];
    r.name = @"NASA Large Image of the Day";
    r.source = @"http://www.nasa.gov/rss/lg_image_of_the_day.rss";
    r.localPath = @"/Users/alex/opt/nasa_lg_image_of_the_day/";
    r.type = @"r";

    [r getImagesFromRSS];
    [r populateArrayFromLocalPath];

    [self.sources addObject: r];
    [r release];
}

 }

【问题讨论】:

  • 如何在 [[sources objectAtIndex: rowIndex] name] 行设置断点,看看断点是什么来源。我也会 NSLog 那一行的结果是什么。
  • 在 objectValueForTableColumn 内部,sources 始终为 null,因此 [[sources objectAtIndex: rowIndex] name] 也为 null。我在这个方法中有一个 NSLog,它显示了源的值和 [[sources ...] name] 的值。

标签: objective-c cocoa macos


【解决方案1】:

我怀疑这是一种竞争条件,其中数组在NSTableView 请求显示数据之前未正确填充,或者在此期间出现了问题。

无论如何,使用NSArrayController 可能有更好的方法来做到这一点。苹果有一个详细的教程,甚至可以做数组的子数组(主/细节视图)。它主要是一些点击工作,并且可能与覆盖或两个一样高级。查看http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaBindings/Tasks/masterdetail.html

使用此方法还应该免费提供排序和过滤等功能,以及更容易维护(取决于您的观点)。

【讨论】:

  • 我一定会调查的。我确实知道该数组在 tableview 请求之前已完全填充。该数组在程序启动时加载,然后显示到程序已加载的文本字段。然后我单击一个按钮,它会打开一个包含 tableview 的新窗口。另外,我注意到当我选择窗口并移动它时,这两种方法都会被调用很多次。 objectValueForTableColumn 始终为数组显示 null。大多数时候 numberOfRowsInTable 显示正确的源数组,但有时它显示为 null。
  • 我可以想到一个对象有时会显示为 nil 有时不显示的两个原因...... 1)您在两个不同的地方定义了它,例如一个 nib 文件,然后也在代码中(其中sources 可以是任意一个)。或者,2)它在分配时没有被正确保留。发布您的初始化代码和 .h 文件中的属性声明(如果相关)。要测试#1,你可以检查retainCount,它可能会照亮一些东西。
  • 另外,当你弄乱非局部变量时,请确保你正在通过你的访问器方法。例如,不要只说value = 10,而是说[self setValue:10]' or self.value = 10`。这可确保您访问的正是您认为的属性。
  • 好的,所以我的 applicationDidFinishLaunching 方法的第一行是 [self loadFromFile]。此方法从文件加载源,如果文件不存在,则创建默认源对象。我将在我的第一篇文章中发布 loadFromFile。
  • 好的,所以我开始在 Interface Builder 中处理 Settings.xib 文件,这改变了很多输出,所以我认为问题可能就在那里。现在,我将“表视图(名称)”链接到应用程序委托文件中的 tableView 对象。这给了我与以前不同的输出。进行该更改后, numberOfRowsInTableView 运行多次,并且每次运行时,源数组都已正确设置。但是,objectValueForTableColumn 永远不会运行,所以表格视图是空的。
【解决方案2】:

好的,所以我终于明白了,虽然我还不能完全确定我是否理解它。你是对的,因为它与源被声明太多次有关,或者类似的东西。

为了让它工作,我需要将 [self sources] 更改为 [[NSApp delegate] sources]。我相信这可以确保访问正确的源对象。我意识到这可能是一种不好的编码习惯,并且大多数教程都建议使用 Singleton 类,但这暂时有效,稍后我会清理它。

我不确定我对 xib 文件所做的更改是否有所作为。我将应用程序委托作为 tableView、委托和数据源链接到表视图。出于某种原因,objectValueForTableColumn 中的 [self sources] 与其他所有方法的 [self sources] 引用的源对象不同,即使它们都在应用程序委托对象中。

【讨论】:

  • 很高兴你能弄明白!我觉得它与文件所有者等有关。单例确实可以正确修复它,或者重新安排应用程序的工作方式。例如,查看this answer,尤其是评论#9。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 2011-08-19
  • 1970-01-01
相关资源
最近更新 更多