Correct use of NSViewController
-
Hi guys,
I've ended up with a bloated window controller in my document based
app and want to refactor my code using done view controllers. My
question is really about design.
If I have a split view with which contains a split view (like mail)
then should I have a controller for the large split view which will
then contain an ivar that points to a controller for the smaller split
view? As a subview of one of the split views I would then have a text
view that itself needs a view controller, so it seems like I'll he
ending up with a heirarchy of view controllers that reflects the view
heirarchy itself. This seems like I'm gong about this the wrong way ad
would end up with a spaghetti code.
Can anyone give mr a few hints as to how this should he fine properly?
Thanks,
Jon -
Hi,
My strategy is similar to yours, but it doesn't have to result in
spaghetti code. I have a view controller class that contains a list
of sub-viewcontrollers. What I end up with is a structure that does
in fact resemble the actual view hierarchy.
The tricky part is breaking down your window controller into logical
units that are as self-contained as possible. In your design, you
don't want the subcontrollers to have dependencies on each other, or
you will end up with spaghetti code. This is where bindings, KVO and
sometimes notifications come in real handy.
So in the case of Mail.app, I could see a window controller with a
singe view controller that returns the main split view as its view.
That controller creates two sub-controllers, the right side and left
side of the main split view. The left side view controller returns
the source list as its view and the right side controller returns the
other split view as its view.
As far as data is concerned, the left side controller's source list
is displaying a list of mail boxes that may be stored in an array
controller somewhere else. Users select a mail box by clicking on
the source list. The right side controller (with the detail/compare
split view) is bound to the "selectedObjects" of that array
controller. When users change the selected objects, the right side
controller is alerted to the change through bindings. It then gets
the selected Mail box and displays what it needs to display. There's
no reason for the right side and left side controllers to communicate
with each other, the bindings mechanism takes care of all of that.
Of course, your controllers don't necessarily need to have the
hierarchical structure of controllers built in to the class. One
advantage of having that relationship in place is that when dealloc
is called on a view controller, it will automatically release all of
the subcontrollers in its list so that you don't have to worry about
memory management for these objects.
I know people that keep dictionaries with the view controllers and
their associated nibs instead of storing them as a tree structure
like I do. I don't know which is the best, but I think that your
instinct that some structure should be there is right.
Hope that helps,
Cathy
On Mar 19, 2008, at 12:37 PM, Jonathan Dann wrote:
> Hi guys,
>
> I've ended up with a bloated window controller in my document based
> app and want to refactor my code using done view controllers. My
> question is really about design.
>
> If I have a split view with which contains a split view (like mail)
> then should I have a controller for the large split view which will
> then contain an ivar that points to a controller for the smaller
> split view? As a subview of one of the split views I would then
> have a text view that itself needs a view controller, so it seems
> like I'll he ending up with a heirarchy of view controllers that
> reflects the view heirarchy itself. This seems like I'm gong about
> this the wrong way ad would end up with a spaghetti code.
>
> Can anyone give mr a few hints as to how this should he fine properly?
>
> Thanks,
>
> Jon
-
Hi Cathy,
Thanks for the comprehensive answer to my question, I wanted to make
sure that I wasn't committing heresy by going down the 'tree of view
controllers' road before jumping in and refactoring all my code. I
was hoping to set it up so I could forget about most of the memory
management as I'm replacing views all over the place at runtime.
Out of interest, when I add my main split view, I then have to set its
size to fit my document window's content view. As this task is view-
related it seems like it the split view's NSViewController should
handle the size calculation and placing of the view in the correct
place in the window. I allocate and instantiate my view controller in
my NSWindowController subclass, then set the split view as a subview
of the content view and then in the -awakeFromNib of the view
controller I get the split view's superview's (the content view's)
frame, doing my resiing from there.
Would you do the same, as this seems to encapsulate the logic
properly, or would you just set it all in the window controller?
Thanks again, you've been really helpful.
Jonathan -
I would do it exactly like you described. Seems to me that your
instincts are pretty much on the mark. In your case, the window
controller could take care of creating that first main split view,
but I would do it in the first level of the view controller
controller tree for logical consistency. So in a set up like mine
and maybe yours, the window controller is only responsible for the
window's content view. It creates the first view controller, asks it
for its view (the split view) and adds it as a subview to its own
view (the window's content view). And actually, when the window
controller asks that first view controller for its view, if things
are set up right in the controller tree, that view should contain the
entire view hierarchy, which was built in nice little steps by each
sub-controller in the tree.
I recently had to refactor my view controller set up because I
started to notice similar bloat and spaghetti code creeping into the
app. I had all of the same questions you do about where things
should happen. :) It was a bit tricky at first, but things fell
into place and it feels very solid and clean to me now. I also deal
with a lot of dynamic adding/removing views.
Actually, I sent a bug report (Bug ID# 5794739) to Apple last week
because the documentation on "Document-Based Application Architecture"
http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/
Concepts/OverviewDocArchitecture.html#//apple_ref/doc/uid/20000023-
BAJBBBAH
hasn't been updated to explain the role of the new NSViewController
class in this design. Also, the issue you are dealing with now and
that I dealt with a couple of weeks ago seems like it should already
be dealt with in the design NSViewController. As it is, it's very
unclear what you're supposed to do with this class.
Anyway, best of luck, you seem to already know what you have to do :)
Cathy
On Mar 20, 2008, at 2:19 AM, Jonathan Dann wrote:
> Hi Cathy,
>
> Thanks for the comprehensive answer to my question, I wanted to
> make sure that I wasn't committing heresy by going down the 'tree
> of view controllers' road before jumping in and refactoring all my
> code. I was hoping to set it up so I could forget about most of
> the memory management as I'm replacing views all over the place at
> runtime.
>
> Out of interest, when I add my main split view, I then have to set
> its size to fit my document window's content view. As this task is
> view-related it seems like it the split view's NSViewController
> should handle the size calculation and placing of the view in the
> correct place in the window. I allocate and instantiate my view
> controller in my NSWindowController subclass, then set the split
> view as a subview of the content view and then in the -
> awakeFromNib of the view controller I get the split view's
> superview's (the content view's) frame, doing my resiing from there.
>
> Would you do the same, as this seems to encapsulate the logic
> properly, or would you just set it all in the window controller?
>
> Thanks again, you've been really helpful.
>
> Jonathan
-
>Hi Cathy,
Thanks again for your advice. I've got it working now and I'm almost
back I where I was before refactoring, I'm now running into a bindings
problem.
Before using the view controllers I had put 2 tree controllers in my
window controller's nib, 2 outline views were then bound to these and
the tree controllers themselves got their content from an object
controller that was bound to the the keypath [(Window Controller)
File's Owner].document. So the object controller was a proxy for my
document and the tree controllers had shorter keypath to traverse to
get to the array they needed in my document subclass.
Now when I do this I have the tree controllers and the document proxy
object controller in my view controller's nib. The only way I can see
to getting to the document is using the keypath
[File's Owner].view.window.windowController.document
However this does not work, seems convoluted, and I get the following:
KVO autonotifying only supports -set<Key>: methods that return void.
Autonotifying will not be done for invocations of -[NSSplitView
_setWindow:]
So my view controller needs to know about its 'owning' document
somehow and I can't see how to get it.
Have you run into this. I'm not sure getting the current document from
the document controller will work as that will change ad the user
opens more documents.
Thanks again,
Jon
P.S. Out of interest, what do you develop? -
Yeah, the document. The window controller and document have a
relationship, but this isn't true for the view controllers and the
document. Again, this is part of NSViewController's ambiguous role
in this whole architecture. I don't really know how this *should* be
dealt with.
It seems like those two key paths would lead to the same thing, but
obviously some connection isn't being made the way you are
expecting. I suspect it has something to do with the fact that the
binding is being set before the view controller's view is actually
added to the view hierarchy, so that view's window isn't the window
controller's window yet which means you have no direct path to the
window controller's document at that moment.
What if you give your view controllers a reference to the window's
window controller when you create them?
Your window controller is obviously the first thing to exist. It
allocates and initializes the first view controller. If you
initialize it with a method like:
- (id)initWithWindowController:(NSWindowController*)theWindowController;
Then they could set their window controller right before they load
their nibs.
The nibs could use this keypath instead:
@"filesowner.windowController.document"
That should hook up correctly if you have a windowController ivar in
your NSViewController subclass.
On Mar 20, 2008, at 12:35 PM, Jonathan Dann wrote:
>>
> Hi Cathy,
>
> Thanks again for your advice. I've got it working now and I'm
> almost back I where I was before refactoring, I'm now running into
> a bindings problem.
>
> Before using the view controllers I had put 2 tree controllers in
> my window controller's nib, 2 outline views were then bound to
> these and the tree controllers themselves got their content from an
> object controller that was bound to the the keypath [(Window
> Controller)File's Owner].document. So the object controller was a
> proxy for my document and the tree controllers had shorter keypath
> to traverse to get to the array they needed in my document subclass.
>
> Now when I do this I have the tree controllers and the document
> proxy object controller in my view controller's nib. The only way I
> can see to getting to the document is using the keypath
>
> [File's Owner].view.window.windowController.document
>
> However this does not work, seems convoluted, and I get the following:
>
> KVO autonotifying only supports -set<Key>: methods that return
> void. Autonotifying will not be done for invocations of -
> [NSSplitView _setWindow:]
>
> So my view controller needs to know about its 'owning' document
> somehow and I can't see how to get it.
>
> Have you run into this. I'm not sure getting the current document
> from the document controller will work as that will change ad the
> user opens more documents.
>
> Thanks again,
>
> Jon
>
> P.S. Out of interest, what do you develop?
-
On 21/03/2008, at 12:35 AM, Jonathan Dann wrote:
>>
> Hi Cathy,
>
> Thanks again for your advice. I've got it working now and I'm almost
> back I where I was before refactoring, I'm now running into a
> bindings problem.
>
> Before using the view controllers I had put 2 tree controllers in my
> window controller's nib, 2 outline views were then bound to these
> and the tree controllers themselves got their content from an object
> controller that was bound to the the keypath [(Window
> Controller)File's Owner].document. So the object controller was a
> proxy for my document and the tree controllers had shorter keypath
> to traverse to get to the array they needed in my document subclass.
>
> Now when I do this I have the tree controllers and the document
> proxy object controller in my view controller's nib. The only way I
> can see to getting to the document is using the keypath
Have you considered using the representedObject property of the
NSViewController?
To quote the API docs for NSViewController:
"...a generic representedObject property, to make it easy to establish
bindings in the nib to an object that isn't yet known at nib-loading
time or readily available to the code that's doing the nib loading."
In my code I create the view controller from the window controller,
then set the representedObject. In my case it's usually the document,
since I have the necessary controller objects in the document so that
I can share selection status across various windows and views from
different NIB's easily (remember that NSDocument is part of the
*controller* layer in MVC, not the model).
HTH, Paul. -
Hi Cathy and Paul,
Thanks to you both for your help, I'm really starting to get somewhere
with this now.
I now have a view controller hierarchy that reflects the views in my
app. I've defined my own view controller subclass that I use and an
abstract superclass for the view controllers I use in the app. To
this 'ESViewController' class I've added a, parent ivar, a mutable
children array and a few indexed accessor methods for that.
To add a new view controller to the hierarchy I use -addChild:
(ESViewController *)vC which has the side-effect of setting the parent
and (originally) the window controller of the child. The parent will
be the view controller that calls -addChild: and the window controller
of the 'root' view controller of the tree is set when I first make the
root view controller.
Cathy, your suggestion of adding the window controller to the views
and their children so I could get the document seemed to work at
first, but I kept getting a warning when closing my document. One of
my children view controllers had an NSObjectController with the
content binding set to @"file's owner.windowController.document",
which worked fine until I tried to close the document. I was told
that the window controller was being deallocated while key-value
observers were still registered with it, which I assume was the
NSObjectController further down in the view hierarchy.
I think this has something to do with retains, as the window
controller was not retained by the view controllers, I couldn't get my
head around who should retain who as my -dealloc methods look like this:
// ESViewController (inherits from NSViewController and used as
abstract superclass for all my view controllers)
- (void)dealloc;
{
parent = nil; // non-retained ivar
self.children = nil;
windowController = nil;
[super dealloc];
}
// ESWindowController (my window controller for my document)
- (void)dealloc
{
self.rootViewController = nil; // rootViewController is an instance
of ESSplitViewController which places a split view in the window's
content view)
[super dealloc];
}
My windowController's -awakeFromNib method set the root view
controller, which when instantiated created its children, setting
their window controllers and parents as such
// ESWindowController
- (void)awakeFromNib;
{
ESSplitViewController *root = [[ESSplitViewController alloc]
initWithNibName:@"SplitView" bundle:nil];
[root setWindowController:self];
[self setRootViewController:root];
[root release];
root = nil;
}
// ESSplitViewController
- (id)initWith..........
{
if (![super init])
return nil;
ESOutlineViewController *oVC = [[ESOutlineViewController alloc]
initWithNibName:@"OutlineView" bundle:nil]; // the OutlineView nib has
the NSObjectController that causes the deallocation grief
ESTextViewController *tVC = [[ESTextViewController alloc]
initWithNibName:@"TextView" bundle:nil];
[self addChild:oVC];
[self addChild:tVC];
[oVC release];
[tVC release];
return self;
}
- (void)addChild:(ESViewController *)child;
{
[child addObject:child];
[child setWindowController:self.windowController];
[child setParent:self];
}
So the way I expected it to work, when deallocating was as follows
windowController gets a -dealloc call
rootViewController gets released and -dealloc'd
childrenViewControllers get released and -dealloc'd
at the end of all this the control returns to the windowController's -
dealloc method which proceeds to call [super dealloc];
Some amount of logging later showed me that my windowController was
calling super before the children began their dealloc methods, which
leads me to assume that maybe the unbinding of the NSObjectController
couldn't happen as the windowController to which it was bound was
already gone.
So this boils down to a couple of ideas
Why could the window controller complete it's deallocation before the
children view controllers have, when they are definitely not retained
elsewhere?
Should the view controllers have retained the window controller and/or
their parent (instinct leads me to think this would cause retain
cycles as the window controller will not call -dealloc as it is
retained by view controllers which it needs to release first).
I later changed this code with Paul's suggestion of using the
represented object as a pointer to my document subclass and all this
went away. The -addChild method now sets the represented object of
the child to that of its parent instead of the window controller. Am
I right in thinking that because of the document architecture the
document cannot be deallocated until the window controller is, so
deallocating the window controller removes the binding before the
document receives -dealloc. In that case, if I did wish to bind
something in my view controllers to the window controller, how can I
avoid all this, is there something more sneaky going on in setting the
representedObject other than just retaining my document? Incidentally
the window controller still calls [super dealloc] before the children
of the root view controller have been deallocated.
Thanks so much to you both for your time, this has really allowed to
to break up my code nicely, an taught me a lot.
Jonathan -
Yeah, this is something I ran into dealing with the fact that I have
several key value observations set up. The way I deal with it is to
give my view controller's abstract superclass a -(void)
removeObservations method. I set it up to work similarly to how you
use the -(void)dealloc method. A subclass removes all observations
that it is registered for and bindings and call's super's
implementation. The super call makes sure all the subcontrollers get
the message as well.
I call this method on the first level controller in from the window
controller in NSWindow's delegate method, - (void)windowWillClose.
It's the only place I can think to have this happen at the right
time. It has to be before the window controller gets released by the
document and dealloced.
when the window controller's dealloc is called, it just releases its
view controller. the view controller superclass releases its mutable
array of subcontrollers.
don't retain the window controller in the view controller class.
This should just be a weak reference. I think you're doing that right.
so for me:
1, window is about to close (wish there was a more reliable place to
do this, but it has to be before dealloc):
windowController:
- (void)windowWillClose
{
[mViewController removeObservations]; // this causes the method to
be called all the way down the view controller tree
}
2. view controller removes it's observations
viewController:
- (void)removeObservations
{
[wArrayController removeObserver:self forKeyPath:@"selectedObjects"];
[super removeObservations];
}
3. The document closes and the window controller is released and
dealloced:
window controller:
- (void)dealloc
{
[mViewController release];
[super dealloc];
}
3. The first view controller is released and dealloced:
viewController:
- (void)dealloc
{
[mSubcontrollers release];
[super dealloc];
}
Everything gets released and dealloced and all observations were
removed before deallocs were called.
Now, I'm not sure about how to deal with bindings that you set up in
Interface Builder in terms of controlling *when* the bindings are
removed and the role of the "representedObject" in all of this.
Would have to do a little bit of research on that.
On Mar 21, 2008, at 9:49 PM, Jonathan Dann wrote:
> Hi Cathy and Paul,
>
> Thanks to you both for your help, I'm really starting to get
> somewhere with this now.
>
> I now have a view controller hierarchy that reflects the views in
> my app. I've defined my own view controller subclass that I use
> and an abstract superclass for the view controllers I use in the
> app. To this 'ESViewController' class I've added a, parent ivar, a
> mutable children array and a few indexed accessor methods for that.
>
> To add a new view controller to the hierarchy I use -addChild:
> (ESViewController *)vC which has the side-effect of setting the
> parent and (originally) the window controller of the child. The
> parent will be the view controller that calls -addChild: and the
> window controller of the 'root' view controller of the tree is set
> when I first make the root view controller.
>
> Cathy, your suggestion of adding the window controller to the views
> and their children so I could get the document seemed to work at
> first, but I kept getting a warning when closing my document. One
> of my children view controllers had an NSObjectController with the
> content binding set to @"file's owner.windowController.document",
> which worked fine until I tried to close the document. I was told
> that the window controller was being deallocated while key-value
> observers were still registered with it, which I assume was the
> NSObjectController further down in the view hierarchy.
>
> I think this has something to do with retains, as the window
> controller was not retained by the view controllers, I couldn't get
> my head around who should retain who as my -dealloc methods look
> like this:
>
> // ESViewController (inherits from NSViewController and used as
> abstract superclass for all my view controllers)
>
> - (void)dealloc;
> {
> parent = nil; // non-retained ivar
> self.children = nil;
> windowController = nil;
> [super dealloc];
> }
>
> // ESWindowController (my window controller for my document)
> - (void)dealloc
> {
> self.rootViewController = nil; // rootViewController is an
> instance of ESSplitViewController which places a split view in the
> window's content view)
> [super dealloc];
> }
>
> My windowController's -awakeFromNib method set the root view
> controller, which when instantiated created its children, setting
> their window controllers and parents as such
>
> // ESWindowController
> - (void)awakeFromNib;
> {
> ESSplitViewController *root = [[ESSplitViewController alloc]
> initWithNibName:@"SplitView" bundle:nil];
> [root setWindowController:self];
> [self setRootViewController:root];
> [root release];
> root = nil;
> }
>
> // ESSplitViewController
> - (id)initWith..........
> {
> if (![super init])
> return nil;
> ESOutlineViewController *oVC = [[ESOutlineViewController alloc]
> initWithNibName:@"OutlineView" bundle:nil]; // the OutlineView nib
> has the NSObjectController that causes the deallocation grief
> ESTextViewController *tVC = [[ESTextViewController alloc]
> initWithNibName:@"TextView" bundle:nil];
> [self addChild:oVC];
> [self addChild:tVC];
> [oVC release];
> [tVC release];
> return self;
> }
>
> - (void)addChild:(ESViewController *)child;
> {
> [child addObject:child];
> [child setWindowController:self.windowController];
> [child setParent:self];
> }
>
> So the way I expected it to work, when deallocating was as follows
>
> windowController gets a -dealloc call
> rootViewController gets released and -dealloc'd
> childrenViewControllers get released and -dealloc'd
> at the end of all this the control returns to the
> windowController's -dealloc method which proceeds to call [super
> dealloc];
>
> Some amount of logging later showed me that my windowController was
> calling super before the children began their dealloc methods,
> which leads me to assume that maybe the unbinding of the
> NSObjectController couldn't happen as the windowController to which
> it was bound was already gone.
>
> So this boils down to a couple of ideas
>
> Why could the window controller complete it's deallocation before
> the children view controllers have, when they are definitely not
> retained elsewhere?
> Should the view controllers have retained the window controller and/
> or their parent (instinct leads me to think this would cause retain
> cycles as the window controller will not call -dealloc as it is
> retained by view controllers which it needs to release first).
>
> I later changed this code with Paul's suggestion of using the
> represented object as a pointer to my document subclass and all
> this went away. The -addChild method now sets the represented
> object of the child to that of its parent instead of the window
> controller. Am I right in thinking that because of the document
> architecture the document cannot be deallocated until the window
> controller is, so deallocating the window controller removes the
> binding before the document receives -dealloc. In that case, if I
> did wish to bind something in my view controllers to the window
> controller, how can I avoid all this, is there something more
> sneaky going on in setting the representedObject other than just
> retaining my document? Incidentally the window controller still
> calls [super dealloc] before the children of the root view
> controller have been deallocated.
>
> Thanks so much to you both for your time, this has really allowed
> to to break up my code nicely, an taught me a lot.
>
> Jonathan
>
-
I'm going down this same path I think. I have a split view with a
browser and a document. The way I solve it is to have the window
controller have outlets to the scroll views of the two panes of the
split view. Then in the window controller I do this:
- (void)windowDidLoad {
[super windowDidLoad];
// Create the browser view controller and give it its data source
browserViewController = [[BTPPBrowserViewController alloc]
initWithScrollView:browserScroller];
[browserViewController setDataSource:[[self document] imageStorage]];
[browserViewController windowDidLoad]; // Allow controller to set up
....
I split the initialization into two parts: the initialization of the
view controller where I provide the superview, and the the
windowDidLoad method where I let it finish setting up now it has its
data source (owned by the document). To tear it down I use:
// Window will close
-(void)windowWillClose:(NSNotification *)notification;
{
// Tell all the view controllers that the window will close
[browserViewController windowWillClose];
}
Of course I will add more view controllers as I create them.
My view controllers hide the view implementation from the higher
levels. My browser is an IKBrowwserView, so I have limited control
over it.
Of course I am still learning, so all of this may be fatally flawed....
On Mar 20, 2008, at 2:53 AM, Cathy Shive wrote:
> Jonathan,
>
> I just wanted to say one more thing. I was re-reading what you had
> written and I see the problem you're having with setting up the
> frame for that first split view.
>
> The problem isn't just the set up of your view controllers and the
> order of creating/adding views, you're also dealing with the issue
> of setting an auto-resizing mask for your view. Wouldn't it be
> great if your view controller for the split view could just
> configure the view to "fill" it's size to match the size of it's
> superview instead of having to explicitly size and position it when
> it's created? This is a flaw in this system. The sub view
> controller has to be able to access the view of its super controller
> so that it can inspect its frame. With the way autoresizing
> currently works in NSView, you're never going to get around this.
>
> So the part of my system that I haven't described, because I just
> realized that it is important to this issue, is that I have coded my
> own resizing behavior into my NSView subclass to add these kinds of
> features. I have a "FillWidthAndHeight" option, for instance (I use
> this one most often). This way I don't have to know the super view's
> frame when I add a subview. At the end of the original window
> controller's init method, I just reset the frame of the window, and
> NSView goes through the view hierarchy and they all size themselves
> correctly within their superviews. In fact, when I create my views,
> many of them are initialized with an NSZeroRect and the first thing
> my window controller does is set the content view of the window to
> be one of my NSView subclasses. This topic is much more difficult
> to tackle, but if you want a truly dynamic view system, your view
> code needs to be able to work without any prior knowledge about the
> super view's and sibling view's frames.
>
> IMHO, this is the the Pandora's Box when it comes to working with
> the view hierarchy. The standard autoresizing mechanism isn't
> really built to handle dynamic layout changes. You always have to
> know the exact size of your view and its position within its
> superview (and sometimes the size and position of sibling views)
> before you set it.
>
> If you need to program a complex, dynamic view system where sizing
> and positioning managed in the code, first subclass NSView and
> figure out a way to deal with autoresizing. Maybe this is a bigger
> project than you have time take on right now and maybe its
> unnecessary for the scope of your project, but you're going to bang
> your head against this issue over and over again as you develop more
> dynamic layouts.
>
> It's important to keep in mind the fact that NSView's autoresizing
> and NSWindowController were created to support interfaces that get
> laid out in IB and don't change much after their awake from nib state.
>
> I really hope that I haven't made the issue more complicated for you!
>
> Cathy
>
>
> On Mar 20, 2008, at 2:19 AM, Jonathan Dann wrote:
>
>> Hi Cathy,
>>
>> Thanks for the comprehensive answer to my question, I wanted to
>> make sure that I wasn't committing heresy by going down the 'tree
>> of view controllers' road before jumping in and refactoring all my
>> code. I was hoping to set it up so I could forget about most of
>> the memory management as I'm replacing views all over the place at
>> runtime.
>>
>> Out of interest, when I add my main split view, I then have to set
>> its size to fit my document window's content view. As this task is
>> view-related it seems like it the split view's NSViewController
>> should handle the size calculation and placing of the view in the
>> correct place in the window. I allocate and instantiate my view
>> controller in my NSWindowController subclass, then set the split
>> view as a subview of the content view and then in the -
>> awakeFromNib of the view controller I get the split view's
>> superview's (the content view's) frame, doing my resiing from there.
>>
>> Would you do the same, as this seems to encapsulate the logic
>> properly, or would you just set it all in the window controller?
>>
>> Thanks again, you've been really helpful.
>>
>> Jonathan
--
Blog: Photos: <A href="http://bagelturf.smugmug.com/">http://bagelturf.smugmug.com/ -
On Mar 21, 2008, at 2:31 PM, Cathy Shive wrote:
> 1, window is about to close (wish there was a more reliable place
> to do this, but it has to be before dealloc):
>
> windowController:
>
> - (void)windowWillClose
> {
> [mViewController removeObservations]; // this causes the method to
> be called all the way down the view controller tree
> }
>
> 2. view controller removes it's observations
>
> viewController:
>
> - (void)removeObservations
> {
> [wArrayController removeObserver:self forKeyPath:@"selectedObjects"];
> [super removeObservations];
> }
>
> 3. The document closes and the window controller is released and
> dealloced:
>
> window controller:
> - (void)dealloc
> {
> [mViewController release];
> [super dealloc];
> }
>
> 3. The first view controller is released and dealloced:
>
> viewController:
> - (void)dealloc
> {
> [mSubcontrollers release];
> [super dealloc];
> }
I do a very similar thing, but name things differently. Instead of
telling the lower objects what to do (remove observations) I tell them
what is happening at the high level so they can do their own thing
based on that (window is closing.. so I'll remove my observers). This
lets me keep everything out of dealloc except for memory management.
In that way if I switch to GC it will still work.
--
Blog: Photos: <A href="http://bagelturf.smugmug.com/">http://bagelturf.smugmug.com/ -
It's so interesting to me to see different people's way of dealing
with this. Seems like everyone's design is very similar - they just
differ in the implementation details.
I hope Apple will fill in the blanks in the framework eventually. We
have all come to the same solution in a certain way, but it would be
easier for us to help each other if we were using the same architecture.
Still, pretty interesting :)
Cathy
On Mar 22, 2008, at 4:31 AM, Steve Weller wrote:
>
> On Mar 21, 2008, at 2:31 PM, Cathy Shive wrote:
>> 1, window is about to close (wish there was a more reliable place
>> to do this, but it has to be before dealloc):
>>
>> windowController:
>>
>> - (void)windowWillClose
>> {
>> [mViewController removeObservations]; // this causes the method
>> to be called all the way down the view controller tree
>> }
>>
>> 2. view controller removes it's observations
>>
>> viewController:
>>
>> - (void)removeObservations
>> {
>> [wArrayController removeObserver:self
>> forKeyPath:@"selectedObjects"];
>> [super removeObservations];
>> }
>>
>> 3. The document closes and the window controller is released and
>> dealloced:
>>
>> window controller:
>> - (void)dealloc
>> {
>> [mViewController release];
>> [super dealloc];
>> }
>>
>> 3. The first view controller is released and dealloced:
>>
>> viewController:
>> - (void)dealloc
>> {
>> [mSubcontrollers release];
>> [super dealloc];
>> }
>
> I do a very similar thing, but name things differently. Instead of
> telling the lower objects what to do (remove observations) I tell
> them what is happening at the high level so they can do their own
> thing based on that (window is closing.. so I'll remove my
> observers). This lets me keep everything out of dealloc except for
> memory management. In that way if I switch to GC it will still work.
>
>
> --
> Blog: http://www.bagelturf.com/ Photos: http://
> bagelturf.smugmug.com/
>
>
>
>



