I\'m trying to implement the new view-based OutlineView as a source list in my Mac app. I can\'t get values to display, though, so I made a small test app from the Core Data app
I have created a little sample project which popuplates also popuplates an NSOutlineView
, not with CoreData but the crucial factor is, like @boaz-stuller stated that the correct cell is selected (similar to how you handle UITableViewCell
s in iOS.
So in my case I have implemented the method like so:
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if ([self isHeader:item]) {
return [outlineView makeViewWithIdentifier:@"HeaderCell" owner:self];
} else {
return [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
}
}
Check out besi/mac-quickies on github. Most of the stuff is either done in IB or can be found in the AppDelegate
This appeared to be a change for Xcode 4 or thereabouts. Interface builder adds two NSTableCellView objects under the NSOutlineView. If you delete the NSTableCellView objects you return to a saner (or at least documented) world where you need would implement the methods:
outlineView:dataCellForTableColumn:item
outlineView:willDisplayCell:forTableColumn:item
...or at least you do if you want a source list look. In any case this is how the SourceView sample is setup and is why, when you try to recreate the SourceView sample that you can get in such a mess.
Alternatively if you want to continue to use the NSTableCellView objects (which are quite useful) then you can:
bind the NSOutlineView 'Content' to your TreeController.arrangedObjects
bind the NSTextField (and/or NSImageView) under NSTableCellView to 'Table Cell View' with a model key path of objectValue.< key >
Wow, it's like me from two weeks ago is asking this question.
Anyway, if you're anything like me, the problem is that,
for view-based NSOutlineViews
, you need to implement the
- (NSView *)outlineView:(NSOutlineView *)outlineView
viewForTableColumn:(NSTableColumn *)tableColumn
item:(id)item;
delegate method and return the NSTableCellView
you set up,
or they'll just give you a blank line. The easiest way to do this is to just call
[outlineView makeViewWithIdentifier:@"MyCell" owner:self]
replacing MyCell
with whatever you typed in as the "User Interface Item Identifier"
in the Identity Inspector for your NSTableCellView
.
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
return [outlineView makeViewWithIdentifier:@"MyCell" owner:self];
}
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
return outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("MyCell"), owner: self)
}
Actually, you don't need to set the delegate. Here is how I got it working (tested with NSTreeController
, but should work with NSArrayController
as well):
arrangedObjects
(without Model Key Path)objectValue.yourCustomValue
TableCellView
. Make sure both identifiers are identical. Repeat that for the remaining columns with different identifiers.Screenshot: Bindings for View Based NSOutlineView
As Boaz noted above, you need to implement the Delegate method to return a view.
Quite a mystery considering I could not find that method in the Docs.
Regarding the type of the (id)item
parameter, it's a NSTreeControllerTreeNode
which is an undocumented subclass of NSTreeNode
. If you cast it you can get the cell's object, and return different view based what kind of object is, or whatever attributes of that object determine the cell view type:
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
NSTableCellView *view = nil;
NSTreeNode *node = item;
if ([node.representedObject isKindOfClass:[Group class]]) {
view = [outlineView makeViewWithIdentifier:@"HeaderCell" owner:self];
} else {
view = [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
}
return view;
}