viewForTableColumn not being called for child items in view-based NSOutlineView

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-08 03:47:30

问题


I have an issue that the method

-(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item;

is not being called when the item isn't a group item. The methods

-(BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item;
-(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;

are implemented to return YES for the (same and) correct set of header/group items. The following methods

-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item;
-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)childIndex ofItem:(id)item;

also return sensible count for children and valid child items respectively. But the above outlineView:viewForTableColumn:item: method is never called for child items. The rows are laid out for children, but are blank (as shown in the screenshot below) since the view-generating method outlineView:viewForTableColumn:item: is never called for children.

Note that I do not have any XIBs and all views are laid out programmatically. In particular, this means I cannot set 'View Based' value for Content Mode on the outline view's underlying table view via the XIB as done in the Apple example code at https://developer.apple.com/library/mac/samplecode/SidebarDemo/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010893 .

If there's a way to do this programmatically, it would be a great help. Although since the view method is called for parent items, not sure if this is the real problem.

Another mystery for me is how the views returned by the following two methods work with each other:

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item;
- (NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item;

Any clues on fixing this would be a great help?


回答1:


Here is some code I put together to show that -(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item; does get called. Maybe by looking at it you could see an error you made somewhere:

// AppDelegate.m

#import "AppDelegate.h"
#import "Item.h"

@interface AppDelegate ()

@property (strong) NSMutableArray *items;
@property (weak) IBOutlet NSWindow *window;

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
    self.items = [NSMutableArray array];

    Item *group1 = [Item itemWithName:@"GROUP 1"];
    [group1 addChild:[Item itemWithName:@"0,0"]];
    [group1 addChild:[Item itemWithName:@"1,0"]];
    [group1 addChild:[Item itemWithName:@"2,0"]];

    Item *group2 = [Item itemWithName:@"GROUP 2"];
    [group2 addChild:[Item itemWithName:@"0,1"]];
    [group2 addChild:[Item itemWithName:@"1,1"]];
    [group2 addChild:[Item itemWithName:@"2,1"]];

    Item *group3 = [Item itemWithName:@"GROUP 3"];
    [group3 addChild:[Item itemWithName:@"0,2"]];
    [group3 addChild:[Item itemWithName:@"1,2"]];
    [group3 addChild:[Item itemWithName:@"2,2"]];

    [self.items addObject: group1];
    [self.items addObject: group2];
    [self.items addObject: group3];

    [self.souceList reloadData];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(Item *)item {
    return !item.parent;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(Item *)item {
    return item.children.count;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(Item *)item {
    if (!item) {
        return self.items[index];
    }

    if (item.children.count > index)
        return item.children[index];
    return nil;
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(Item *)item {
    if (!item) {
        return self.items.count;
    }
    return item.children.count;
}

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(Item *)item {
    // Breakpoint set here to test
    return [[NSView alloc] init];
}

@end

// Item.h
@interface Item : NSObject
@property (weak) Item *parent;
@property (copy) NSString *name;

+ (instancetype)itemWithName:(NSString *)name;
- (instancetype)initWithName:(NSString *)name;

- (void)addChild:(Item *)child;
- (void)removeChild:(Item *)child;

@end

@interface Item (Property)
@property (readonly, strong) NSArray *children;
@end

// Item.m

#import "Item.h"

@interface Item ()
@property (readwrite, strong) NSMutableArray *children;
@end

@implementation Item

+ (instancetype)itemWithName:(NSString *)name {
    return [[self alloc] initWithName:name];
}

- (instancetype)initWithName:(NSString *)name {
    if ((self = [self init])) {
        self.name = name;
    }
    return self;
}

- (id)init {
    if ((self = [super init])) {
        self.name = @"No Name";
        self.children = [NSMutableArray array];
    }
    return self;
}

- (void)addChild:(Item *)child {
    child.parent = self;
    [self.children addObject: child];
}
- (void)removeChild:(Item *)child {
    if (child.parent == self)
        child.parent = nil;
    [self.children removeObject:child];
}

@end

Regarding your second question about the View-based status of NSTableView/NSOutlineView: that value is set automatically depending upon which delegate/datasource methods are implemented. If you are implementing -(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item;, then the view will be treated as view-based.

As for your last question regarding these two:

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item;
- (NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item;

The second method relates to a view which spans the width of the table, encompassing the cell views for every table column. Meaning you have several cell views - one for each column - returned by the first method which are subviews of the one view returned by the second for each row.



来源:https://stackoverflow.com/questions/24774492/viewfortablecolumn-not-being-called-for-child-items-in-view-based-nsoutlineview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!