objective-c - NSOutlineView - 正在返回对象值,但仅显示占位符标题 "Table View Cell"

标签 objective-c cocoa nsoutlineview

我正在编写一个暂时称为“CocoaMix”的小型应用程序,其目的是测试我为访问各种 UI 上的辅助功能层次结构而编写的代码。本质上,我想要完成的是测试用户界面左侧的 NSOutlineView 和右侧的“示例” View 。

到目前为止,对于数据源实现,我有:

@interface CMTopLevelCategory : NSObject

@property (readonly) NSString *name;

@property (readonly) NSArray *examples;

- (id)initWithName:(NSString *)name examples:(NSArray *)examples;

@end


@interface CMExample : NSObject

@property (readonly) NSString *name;

- (id)initWithName:(NSString *)name;

@end


@interface CMSideOutlineViewDataSource : NSObject <NSOutlineViewDataSource>

@end


//...


#define CMNameColumnIdentifier @"name"
#define CMCountColumnIdentifier @"count"

@interface CMSideOutlineViewDataSource ()

@property NSArray *topLevelCategories;

@end

@implementation CMSideOutlineViewDataSource

- (id)init {
    self = [super init];
    if (self) {
        CMExample *largeTableExample = [[CMExample alloc] initWithName:@"Large Table"];
        CMTopLevelCategory *tablesCategory = [[CMTopLevelCategory alloc] initWithName:@"Tables" examples:@[ largeTableExample ]];

        _topLevelCategories = @[ tablesCategory ];
    }
    return self;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    if (item) {
        if ([item isKindOfClass:CMTopLevelCategory.class]) {
            CMTopLevelCategory *topLevelCategory = item;
            return [topLevelCategory.examples objectAtIndex:index];
        }
    } else {
        return [self.topLevelCategories objectAtIndex:index];
    }
    return nil;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    return [item isKindOfClass:CMTopLevelCategory.class];
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    if (item) {
        if ([item isKindOfClass:CMTopLevelCategory.class]) {
            CMTopLevelCategory *topLevelCategory = item;
            return [topLevelCategory.examples count];
        }
    } else {
        return [self.topLevelCategories count];
    }
    return 0;
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
    if ([item isKindOfClass:CMTopLevelCategory.class]) {
        CMTopLevelCategory *topLevelCategory = item;
        if ([tableColumn.identifier isEqualToString:CMNameColumnIdentifier]) {
            return topLevelCategory.name;
        } else if ([tableColumn.identifier isEqualToString:CMCountColumnIdentifier]) {
            return [NSNumber numberWithUnsignedInteger:[topLevelCategory.examples count]];
        }
    } else if ([item isKindOfClass:CMExample.class]) {
        CMExample *example = item;
        if ([tableColumn.identifier isEqualToString:CMNameColumnIdentifier]) {
            return example.name;
        }
    }
    return @"default value";
}

@end

为了解释这一点,顶级项目应该是诸如“表格”之类的示例类别,然后对于每个类别,都会有一些示例 UI(例如,示例的“表格”类别中的“大表格”) )。

当我构建并运行时,我在 outlineView:objectValueForTableColumn:byItem: 中设置的断点被触发,但 NSOutlineView 中的文本仍然是占位符“Table”单元格 View ”文本:

Screenshot of the "CocoaMix" application window

我做错了什么?

最佳答案

我将进行一些猜测。您可能正在使用基于 View 的大纲 View 。单元格 View 可能是 NSTableCellView,每个 View 中都有一个 NSTextField

大纲 View 采用数据源从其 -outlineView:objectValueForTableColumn:byItem: 方法返回的对象值,并在单元格 View 上调用 -setObjectValue:,如果它响应该方法。 NSTableCellView 确实如此。

所以,现在您的表格单元格 View 已经设置了其 objectValue。那有什么作用?可能什么也没有。

您可以使用绑定(bind)将 subview 绑定(bind)到表单元格 View ,其中关键路径经过objectValue。因此,您可以使用 objectValue 键路径将文本字段的 Value 绑定(bind)绑定(bind)到表格单元格 View 。这将导致文本字段显示该值。

另一种方法是子类化 NSTableCellView 并使用该自定义子类作为大纲 View 中的单元格 View 。然后,重写 -setObjectValue:,除了调用 super 之外,您还可以将对象值传递给 subview 。要访问 subview ,您可以将它们连接到 NSTableCellView 的标准 textFieldimageView 导出,或者您可以向自定义子类添加更多导出,在 IB 中连接它们并使用它们。

我认为绑定(bind)方法是最简单的。此外,它还提供了更大的灵活性。您的 -outlineView:objectValueForTableColumn:byItem: 实现可能只返回 item。然后,文本字段的绑定(bind)可以使用 objectValue.name 作为模型关键路径。如果您添加更多 subview ,它们可以使用不同的关键路径来显示项目的不同方面。

对于不同的列,您将使用不同的单元格 View 子层次结构,并且这些 subview 的绑定(bind)将使用不同的键路径,但使用相同的 objectValue。这个想法是,行代表给定的项目,因此 objectValue 将是该项目,而列将仅使用该项目的不同属性。

如果您确定大纲 View 在单元格 View 中只有文本字段,另一种可能的方法是根本不使用 NSTableCellView (或子类)。相反,请使用裸 NSTextField 作为单元格 View 。在这种情况下,当大纲 View 在单元格 View 上调用 -setObjectValue: 时,这将是文本字段(响应该方法),并且将设置其值,无需额外的步骤。

关于objective-c - NSOutlineView - 正在返回对象值,但仅显示占位符标题 "Table View Cell",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26330468/

相关文章:

objective-c - Cocoa:将音频附加到现有文件

objective-c - NSOutlineView 与目录的拖动 promise

macos - NSOutlineViewDataSource 和 swift

objective-c - 显示占位符标记时如何控制 NSTextField 的文本颜色?

iOS模拟器: Changing language does not change format of [NSDate date] output

objective-c - 使用 Storyboard连接向下钻取的 NSSplitView socket

macos - swift —— "Cannot find object class with name"

swift - NSOutlineView 中行的背景颜色

objective-c - 初学者对 obj-c 中从另一个实例访问一个实例感到困惑

ios - didReceiveRemoteNotification : fetchCompletionHandler: download freezes