Skip navigation.
 
mlRe: beyond MV and (one) C
FROM : Ken Thomases
DATE : Sun Jan 20 11:45:15 2008

On Jan 18, 2008, at 2:09 PM, Daniel Child wrote:

>
> On Jan 13, 2008, at 1:35 PM, mmalc crawford wrote:
>

>> Additional controllers come into play if you want to devolve 
>> responsibility for managing a fairly self-contained subset of the 
>> UI to a separate controller.  NSWindowController is perhaps the 
>> "biggest granularity" example where rather than an NSDocument 
>> instance being responsible for multiple windows it can devolve 
>> responsibility to individual window controllers.  A window 
>> controller might then devolve responsibility for managing, say, a 
>> table view to an NSArray controller.  Or for a custom view you 
>> might implement your own NSViewController. It's all up to you to 
>> decide how you want to factor out the workload.

>
> I think I understand why you might devolve responsibility to window 
> controllers in a doc app. I don't see what they do in a non-doc app, 
> however.
>
> More importantly, how you get the window controllers working in the 
> first place? The description of controller objects "owning" 
> mediating controllers  (in "MVC Design Patterns") is totally 
> abstract to me until I see an example of how this is done.
>
> To test the idea, I created an app with two nibs:
>
> MainMenu.nib -- contains WindowA and WindowB
> WindowC.nib  -- contains WindowC
>
> Each window has a button to reference the other two. (Open Window A, 
> Open Window B, etc.)
>
> MainMenu.nib has an instance of a (typical) Controller (subclass of 
> NSObject) that has code for windows A and B.
>
> WindowC.nib has an instance of a WindowCController that is a 
> subclass of NSWindowController, and has code for the actions of 
> Window C (openA and openB).


The nib should not contain an instance of a NSWindowController-derived 
class.  An NSWindowController is intended to be the owner of the nib. 
As such, it's outside of the nib -- "above" it, in a certain sense. 
So, when it comes time to load WindowC.nib, you do:

   WindowCController* myWindowCController = [[WindowCController alloc] 
initWithWindowNibName:@"WindowC"];

In the nib, you would set the class of File's Owner to 
WindowCController.  You'd also connect its "window" outlet to the 
window in the nib.  Then, anywhere that some other part of the code 
needs to refer to WindowC, you use this expression:

   [myWindowCController window]

If you want the WindowCController instance to know about the other 
windows, you can add some ivars to it and set them up.  You can do 
that immediately after the alloc-init statement, above, or actually 
define your own custom init... method that takes additional arguments.

One thing that might be confusing you: you might want a controller 
which manages the window controllers.  Often, there's an application 
controller, which might also be the application delegate.  This 
application controller is what knows about the various nibs and window 
controller classes.  So, it is what would allocate and initialize the 
WindowCController instance, as illustrated above except that 
myWindowCController would not be a local variable, it would be an 
instance variable.  The application controller would also have the 
"global" overview sufficient to connect the various nibs and window 
controllers to each other.


> Also, how will the different nibs know about each other? When I 
> instantiate the WindowCController, there seems to be no recognition 
> of the fact that I had declared an IBOutlet NSWindow *windowC or 
> IBActions (openA, openB). In other words, the instantiated subclass 
> of NSWindowController does not behave like a regular controller in 
> terms of the target-action paradigm.


I'm not sure I followed this part.  What does "a regular controller in 
terms of the target-action paradigm" mean?

Remember that you can target actions to the First Responder, as well 
as a customer controller instance in the nib.  And, if you do that, 
then the application delegate is automatically included in the 
responder chain that will be asked to handle the action.  See <http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/chapter_2_section_6.html#//apple_ref/doc/uid/10000060i-CH3-SW9
>.  So, you can put the openA, openB, and openC methods in the 
application delegate and any of your buttons will be able to invoke 
them.

It's also perfectly acceptable to target the actions to the File's 
Owner, which would be your custom subclass of NSWindowController.  If 
you're worried about duplicate code appearing in all of your 
controller subclasses, figure out where the responsibility truly 
should live, put it there, and just have the window controllers 
forward the request.  In other words, WindowCController could have an 
openA: action method which just forwards the request to some method of 
the application controller.

How does a WindowCController get a pointer to the application 
controller?  Well, it could be given one explicitly by the application 
controller when it creates the WindowCController instance.  Or, the 
WindowCController can just use [NSApp delegate].

-Ken

Related mailsAuthorDate
mlbeyond MV and (one) C Daniel Child Jan 13, 17:59
mlRe: beyond MV and (one) C mmalc crawford Jan 13, 19:35
mlRe: beyond MV and (one) C mmalc crawford Jan 13, 20:24
mlRe: beyond MV and (one) C Daniel Child Jan 18, 21:09
mlRe: beyond MV and (one) C Ken Thomases Jan 20, 11:45
mlRe: beyond MV and (one) C mmalc crawford Jan 20, 11:58
mlRe: beyond MV and (one) C Ken Thomases Jan 20, 14:21
mlRe: beyond MV and (one) C Daniel Child Jan 21, 05:57