How would you Subclass an NSOutlineView?
-
3The short answer is: the same way you subclass any object. You should try and be more specific with your questions. Apple's documentation covers subclassing and so we must assume you've read that and tried something and then got stuck. Where have you got stuck? – Chris Suter Jun 14 '09 at 08:46
-
Sorry I hadn't read all the Apple Docs on Sub-Classing. – Joshua Jun 14 '09 at 13:54
2 Answers
Firstly, before you subclass an object, you should ask yourself "do I need to do this?". Subclassing is a more complex way of interacting and extending the functionality of other classes, so you should make sure that what you are trying to achieve cannot easily be achieved through another, simpler method, such as delegation, notifications etc. Obviously if you are trying to change the way the control looks this is going to be more easily accomplished through subclassing, but make sure you check all the other available options. Remember that NSOutlineView
has a fairly long object tree - it inherits from NSTableView
, which inherits from NSControl
, which inherits from NSView
, which inherits from NSResponder
which inherits from NSObject
, and there are various helper methods that exist in each of these classes which can often help you achieve what you want.
However, if you check all of these options and decide to subclass NSOutlineView
, it depends what you want to do with your subclass. The easiest way to create the shell of your subclass would be to select File > New File
then choosing Objective-C class
, as you would with any other class, which will create a new class, with header and implementation files, that inherits from NSObject
. Then you can simply change the line in your header file:
@interface MyClass : NSObject { // Where MyClass is the name of your class
to
@interface MyClass : NSOutlineView {
which will cause your class to inherit from NSOutlineView
. Since it is a subclass of NSOutlineView
, this gives you lots of opportunities to change the default behaviour of the control.
Since you are creating a subclass, you can change the default implementation of any method up the object tree - that is, you can override methods declared in NSOutlineView
, NSTableView
, NSControl
, NSView
, NSResponder
and NSObject
(although you should rarely override methods declared in NSObject
). You do not need to redefine the method signature in your header file, you can simply override the function by implementing it in your subclass's implementation. For example, if you wanted to override NSView
's drawRect:
method, you would do the following in your subclass's implementation:
- (void)drawRect:(NSRect)rect //Method signature from the docs
{
//Code here
}
When drawRect:
is called upon your class, your code will be executed instead of the code in NSView
.
You can also pass method calls up the tree for methods that you do not want to handle. This is done by default, so you do not need to create empty methods that simply call the method on super
, however, if you override a method and want to allow one of your superclasses to handle it first, you could do the following:
- (void)expandItem:(id)item
{
[super expandItem:item];
//Your code here
}
This would be beneficial if you wanted to change a variable in your class, for example, but provide the default implementation of the method by first passing the method call up the tree.
Subclassing can be a rather complex process, especially for such a complex object as a control, although it can be very useful and powerful.

- 37,815
- 10
- 68
- 69
-
Wow! Thanks very much for this great answer! I have put the code in that I want to use but, I get an error with the code I used, I was wondering if you could help me solve the problem. Here is the code. http://fwdr.org/w3cr .The Problem I have is that i get an error saying 'rowIndex' is un-declared but I don't know what to declare as (I mean whether it is an NSArray etc.). I wondered if you could help, seeing as though it is why I had to subclass NSOutlineView in the first place. Thanks Again for the Great Answer. And sorry about this long comment. – Joshua Jun 14 '09 at 08:52
-
That was what I was trying to say at the beginning of my post - if you look in the docs, outlineView:willDisplayCell:forTableColumn:item: is a delegate method; therefore if you only want to override this method then you do not need to subclass NSOutlineView; you can simply make your controller class a delegate of your NSOutlineView, and then implement that method there. As for your sample, you want to call rowForItem: on the outline view, passing anItem as the argument to retrieve the row index. – Alex Rozanski Jun 14 '09 at 08:58
-
The reason I am trying to sub-class NSOutlineView to do this is because it said to do so where I got the code from (http://www.cocoadev.com/index.pl?AlternatingRowColors) – Joshua Jun 14 '09 at 13:12
-
If you're only implementing the outlineView:willDisplayCell:forTableColumn:item: method, you don't need to subclass NSOutlineView. If you are looking at the Apple code example further down the page where you have to do actual drawing then you need to subclass NSOutlineView. – Alex Rozanski Jun 14 '09 at 13:26
-
The code I was using was the code at the top of the page. If i did not sub-class NSOutlineView for that how would I need to change the code? – Joshua Jun 14 '09 at 13:49
-
Thanks, I didn't notice that code near the bottom of the page, So I had a go at using the Apple Code with the Sub-Class and it just about worked but I get a warning saying ''MyOutlineView' may not respond to '-drawStripesInRect:''. Do you know how I might fix this problem? – Joshua Jun 14 '09 at 13:53
-
Did you declare the drawStripesInRect: method in your NSOutlineView subclass? Check the method declaration and make sure to declare it in your class header file. – Alex Rozanski Jun 14 '09 at 14:21
-
-
You would simply declare it in the class implementation like any other class method. – Alex Rozanski Jun 14 '09 at 15:52
-
How would you declare it? Would it be a bit like this … NSArray *objectArray; but saying drawStripesInRect and NS Something? – Joshua Jun 14 '09 at 16:52
-
You'd declare it as - (void) drawStripesInRect:(NSRect)clipRect after the curly braces but before the @end. – Alex Rozanski Jun 14 '09 at 17:21
-
Ahh I See, That Now gets rid of the error but now I get another error on the line #import "MyOutlineView.h" saying 'syntax error before 'AT_NAME' Token'. – Joshua Jun 14 '09 at 17:46
-
Sorry, I missed out the semicolon at the end of the declaration. It should be - (void) drawStripesInRect:(NSRect)clipRect; – Alex Rozanski Jun 14 '09 at 17:55
-
No Problem, All the code works now but It has not affected the Outline View, is there something i need to do to connect the two so they will work? – Joshua Jun 14 '09 at 18:07
-
Perhaps you should start a new question? It will attract a larger audience and you can get a specific answer to what you want. – Alex Rozanski Jun 14 '09 at 18:24
-
Perhaps So, what do you think would be the best title to attract a larger audience? – Joshua Jun 14 '09 at 18:31
-
That's up to you - I was just saying that your question has deviated from your original question, and is more specific so perhaps it would be better placed as a new question. – Alex Rozanski Jun 14 '09 at 18:36
-
The New Question Is Here, http://stackoverflow.com/questions/993465/nsoutlineview-not-doing-what-it-has-should-do-in-its-subclass . – Joshua Jun 14 '09 at 18:48
@interface MyOutlineView : NSOutlineView
{
...
}
...
@end

- 242,470
- 58
- 448
- 498

- 57,021
- 16
- 130
- 131
-
-
Oh i put my code there. Would I need to put anything in the header file? – Joshua Jun 14 '09 at 07:57
-
That is what goes in the header file; the first `...` is for instance variables, the second for method signatures. The .m contains the `@implementation MyOutlineView ... @end` with your actual method... implementations. – Noah Witherspoon Jun 14 '09 at 08:06
-
I see, would this class file have to be the Outline View's data source? – Joshua Jun 14 '09 at 08:24