KVO de-observation difficulties when closing a window

  • This is proving a lot harder that I feel it should be.

    I am KVO observing the accessory view property of an NSRulerView, so that I can install different views into the accessory area when the standard text controls are removed. The ownership of the NSRulerView is quite complicated, as it's part of an NSScrollView, which in turn is owned by a bunch of other views and ultimately the window.

    I can remove my KVO observation in the window delegate's -windowWillClose: method, and that's fine as far as it goes. But it's not always called, leaving me with the dreaded 'KVO observers were still attached when an object was deallocated' error in some cases (in particular, when the 'Save' dialog shows up and Don't Save is clicked - maybe for other cases as well).

    Is there a place I can reliably get notified when a window will close, no matter what pathway it took to close that window, whether a save was involved, whether it was closed by a manual click in the close button or closed by some other means, but BEFORE any of its internal structure is released (views in particular)? Surely there's a reliable place for this?

    Ideally I'd prefer a delegate method since I'm not subclassing NSWindow in this case.

    --Graham
  • Observe NSWindowWillCloseNotification via NSNotificationCenter. You will get notified. The delegate should get the notification but it's possible the delegate is getting set nil prior.

    On May 13, 2012, at 6:18 PM, Graham Cox wrote:

    > This is proving a lot harder that I feel it should be.
    >
    > I am KVO observing the accessory view property of an NSRulerView, so that I can install different views into the accessory area when the standard text controls are removed. The ownership of the NSRulerView is quite complicated, as it's part of an NSScrollView, which in turn is owned by a bunch of other views and ultimately the window.
    >
    > I can remove my KVO observation in the window delegate's -windowWillClose: method, and that's fine as far as it goes. But it's not always called, leaving me with the dreaded 'KVO observers were still attached when an object was deallocated' error in some cases (in particular, when the 'Save' dialog shows up and Don't Save is clicked - maybe for other cases as well).
    >
    > Is there a place I can reliably get notified when a window will close, no matter what pathway it took to close that window, whether a save was involved, whether it was closed by a manual click in the close button or closed by some other means, but BEFORE any of its internal structure is released (views in particular)? Surely there's a reliable place for this?
    >
    > Ideally I'd prefer a delegate method since I'm not subclassing NSWindow in this case.
    >
    >
    > --Graham
  • Turns out the problem was more complicated than I first though, and I have solved it.

    -windowWillClose: is reliably called in all cases, whether or not the Save dialog gets involved.

    The problem was that I was setting up observation in my document's -awakeFromNib method, which as we know can be called multiple times. That in itself was OK, since the set up did its own checks to avoid observing more than once. However, in Lion, document objects get made at odd, surprising times in order to support Versions. So a second phantom document object is being made as soon as the Save dialog is displayed on the first document. Why Lion does this at that moment is something of a mystery, but it does. This second document sets up a new observer on a new ruler view, though its window is never displayed. As a result, the windowWillClose method of the phantom document isn't called and the observation is never cleaned up before the phantom document is deallocated. This second document's role in the whole shebang is not understood (by me at any rate) - perhaps it's just there to deliver the block of data to be saved asynchronously.

    Moving all the observation setup to -windowControllerDidLoadNib: instead solves the problem, since this does not get invoked for these Lion phantom documents.

    It also made me notice a few other potentially problematic setups in awakeFromNib that needed moving.

    I think the lesson here is that on Lion, you need to allow Cocoa a lot more leeway with your document objects that you might be used to on earlier systems. I guess it's not unusual to treat your document as a stand-in for a window controller, especially as for basic document-based apps you don't need a separate window controller subclass, but you have to be aware that Cocoa will create these document objects for its own purposes that might conflict with its role as a window controller. Lesson learned.

    --Graham

    On 14/05/2012, at 11:18 AM, Graham Cox wrote:

    > This is proving a lot harder that I feel it should be.
    >
    > I am KVO observing the accessory view property of an NSRulerView, so that I can install different views into the accessory area when the standard text controls are removed. The ownership of the NSRulerView is quite complicated, as it's part of an NSScrollView, which in turn is owned by a bunch of other views and ultimately the window.
    >
    > I can remove my KVO observation in the window delegate's -windowWillClose: method, and that's fine as far as it goes. But it's not always called, leaving me with the dreaded 'KVO observers were still attached when an object was deallocated' error in some cases (in particular, when the 'Save' dialog shows up and Don't Save is clicked - maybe for other cases as well).
    >
    > Is there a place I can reliably get notified when a window will close, no matter what pathway it took to close that window, whether a save was involved, whether it was closed by a manual click in the close button or closed by some other means, but BEFORE any of its internal structure is released (views in particular)? Surely there's a reliable place for this?
previous month may 2012 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today