• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Correct use of NSViewController
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Correct use of NSViewController


  • Subject: Re: Correct use of NSViewController
  • From: Cathy Shive <email@hidden>
  • Date: Fri, 21 Mar 2008 22:31:56 +0100

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


_______________________________________________

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


  • Follow-Ups:
    • Re: Correct use of NSViewController
      • From: Steve Weller <email@hidden>
References: 
 >Correct use of NSViewController (From: Jonathan Dann <email@hidden>)
 >Re: Correct use of NSViewController (From: Cathy Shive <email@hidden>)
 >Re: Correct use of NSViewController (From: Jonathan Dann <email@hidden>)
 >Re: Correct use of NSViewController (From: Cathy Shive <email@hidden>)
 >Re: Correct use of NSViewController (From: Jonathan Dann <email@hidden>)
 >Re: Correct use of NSViewController (From: Cathy Shive <email@hidden>)
 >Re: Correct use of NSViewController (From: Jonathan Dann <email@hidden>)

  • Prev by Date: Re: dealloc methods not being called?
  • Next by Date: Re: Intercepting retain/release of object
  • Previous by thread: Re: Correct use of NSViewController
  • Next by thread: Re: Correct use of NSViewController
  • Index(es):
    • Date
    • Thread