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?
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