Re: Correct use of NSViewController
Re: Correct use of NSViewController
- Subject: Re: Correct use of NSViewController
- From: Jonathan Dann <email@hidden>
- Date: Fri, 21 Mar 2008 20:49:33 +0000
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
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden