PDA

View Full Version : Using custom derived object classes instead of direct objects provided by Cocoa




acidity
Jan 31, 2008, 07:55 AM
Hello

So I started writing my first real life Cocoa application after moving from Windows one year back. The interface for the main window of Ecto (a blogging client). Screenshot at: http://ecto.kung-foo.tv/xshots/main.png. Thus the main window will have a NSOutlineView on left and on the right hand side, a NSTableView and NSTextView on right separated by a horizontal NSSplitView. The NSOutlineView is separated by the other two windows by a vertical NSSplitView.

So I create those controls in the MainWindow by dragging the NSOutlineView and other objects in IB and set the datasource of the controls to be the main AppController object. So all the windows datasource is the main AppController.

Instead of doing this, I would like to have my own custom class e.g. FolderView which is derived from NSOutlineView and use that in the mainwindow. So instead of all the datasource messages sent to AppController it will send them to their individual class.

Thus instead of having something like:


AppController.h

@implementation AppController : NSObject

@interface AppController : NSObject {
IBOutlet NSOutlineView *outlineView;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item;
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item;
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;


I would ideally like to have


AppController.h

@interface AppController : NSObject {
IBOutlet FolderView *outlineView;
}

@end

FolderView.h

@interface FolderView : NSOutlineView
{
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item;
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item;
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;

@end


How can I do this in XCode 3.0? I would like to separate all the main object controls into separate classes which handles their own job.



iSee
Jan 31, 2008, 12:17 PM
Check out NSViewController, which is new for Leopard.

BTW, I'm just starting to learn Cocoa, and haven't used NSViewController yet, but from what I understand, it is useful for encapsulating controller logic particular to a view. I believe you would subclass NSViewController (rather than your the NSView-derived classes) and use instances for your custom NSViewController to wrap instances of your standard NSView-derived objects.

The conceptual documentation on it seems a little light, but apparently you can get the right idea by reading about NSWindowController: NSViewController is to NSView as NSWindowControll is to NSWindow.

Maybe one of the experienced Cocoa programmers here can tell if I'm sending you on a wild goose chase or not.

By the way: I first heard about NSViewController by listening to a good Cocoa programmer podcast called "Late Night Cocoa" (or something like that). It's amazingly good considering the limitations of the format have in regard to programming topics. I think you need to have an understanding of the topics covered to get a lot out of it so I think it's most useful for experienced programmers new to Cocoa.

Nutter
Jan 31, 2008, 12:37 PM
This is not a good idea. Why would an object respond to its own delegate messages? Why should a view provide information (to itself!) about model objects?

These delegate messages should be implemented by a controller object — that's the whole point of offering delegate messages.

See here (http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/chapter_5_section_4.html) for more information on the MVC design pattern.

acidity
Feb 1, 2008, 01:17 AM
This is not a good idea. Why would an object respond to its own delegate messages? Why should a view provide information (to itself!) about model objects?

These delegate messages should be implemented by a controller object that's the whole point of offering delegate messages.

See here (http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/chapter_5_section_4.html) for more information on the MVC design pattern.

Make sense. I used to code like that in Windows all the time. I guess the habits are still there......I have read that document before. I will read it again.

Why I was thinking this was becase I want to implement various object methods in a different .m file so that it keeps the code clean.

On a side note, which control is used by Apple Mail for showing the folder on left hand side? Its is also used in Acquisition (http://www.acquisitionx.com/)

acidity
Feb 1, 2008, 02:26 AM
Also, my question arised as I downloaded the source code for Vienna (an RSS client that I use) to see how a real world Cocoa app is designed. Their main window has similar interface to the one described above with a SPOTLIGHT like search window.

When I opened their MainMenu.nib, it had many custom objects derived from NSView and then each NSView was placed in the main window. I read through the source code and try figure out the architecture but couldnt. I read tutorials on NSView and all of them was about having an NSView when you have to draw a custom control. Thus, I was and am still confused. A screenshot of its MainMenu.nib attached.

Maybe, I should stop looking at other project code and start on my own in simple ways.

kainjow
Feb 2, 2008, 01:48 PM
On a side note, which control is used by Apple Mail for showing the folder on left hand side? Its is also used in Acquisition (http://www.acquisitionx.com/)

I'm not sure which control you mean, but most likely it's a custom control. Post a screenshot and I'll tell you.

I wouldn't try to figure out how Vienna is doing things, it'll probably just confuse you even more. Just take it a step at a time and figure out how your program does things. As you learn more you'll figure out new better ways to do what you've already done.

Also on using a custom NSOutlineView, generally in Cocoa you don't override a view to provide custom model behavior, but you do it for custom interface behavior. Model behavior is defined by what your model is doing :). What you can do, is create a separate controller object for your outline view, and have that wrap some outline view delegate methods, so that you can more easily implement the same thing again.

acidity
Feb 3, 2008, 09:48 AM
Image attached. Basically I want a flat outlineview like Mail.app with the + sign control at the botoom to specify adding another account.

Even I realised that the best way to learn was to write my own small apps and see what they are doing. Did indeed that for 2 days and learnt a lot but then the curiosity got the better of me again and I opened up Vienna's code. With more careful reading and knowledge gained in the last two I was able to figure out how the NSView and the contros are interacting. Basically they have implemented View for all major controls and then the controls dleegate is the view so all the view code of that control is provided in their corresponding view object. Makes sense.

Now back to reading and figuring out to best store application spepcifric preference data like window position, dimenstion, color, font preferences etc. Any suggestions on that?

acidity
Feb 3, 2008, 09:58 AM
Sorry the attachment.

kainjow
Feb 3, 2008, 10:32 AM
Image attached. Basically I want a flat outlineview like Mail.app with the + sign control at the botoom to specify adding another account.

That is a normal NSOutlineView with a background color, and a custom NSCell for each row to draw the total unread messages count. It probably doesn't have a border either, but I can't tell.

The buttons at the bottom are custom NSButtons and NSPopUpButtons. I have implemented those style of controls before and there are a lot of ways you can do it, but it is custom code, not part of Cocoa.

Now back to reading and figuring out to best store application spepcifric preference data like window position, dimenstion, color, font preferences etc. Any suggestions on that?

Read up on the NSUserDefaults class. Also, NSWindows can save their position and size to the user defaults automatically. Read the docs on those classes.

acidity
Feb 3, 2008, 12:17 PM
Thanks for the response. Help much appreciated. I can already see an awesome time coding in Cocoa. Whatever I have written till now...I am impressed. Definitely better then Win32 that I was used to for 5 yrs :)

BTW, do you know of any tutorial about making such custom control with custom NSOutline, NSButton and NSopupbutton and how to effectively use them in a combined view?

Otherwise, I am back to reading the official Apple docs on the following objects.