Re: NSAutounbinder not releasing my object in a timely manner
Re: NSAutounbinder not releasing my object in a timely manner
- Subject: Re: NSAutounbinder not releasing my object in a timely manner
- From: Jonathan Taylor <email@hidden>
- Date: Thu, 19 Jul 2012 12:02:13 +0100
>>>> this nasty NSAutounbinder thingy then jumps in and re-retains it in some evil under-the-covers voodoo to do with avoiding retain cycles (as I understand it). Unfortunately the balancing autorelease only occurs 16 seconds later when I move the mouse! While not catastrophic this is pretty annoying and looks rather embarrassing.
>>
>>> It's not embarrassing unless your users are running your app in a debugger.
>>
>> Sorry, you've lost me there. Are you saying this will not occur if I am running standalone rather than under XCode? (Unfortunately I don't have the code in front of me to try this out). If that is the case then that's good - if frustrating - news. Is this a known issue then? I was working on the assumption that I was doing something obscurely wrong, or at least non-standard somewhere to trigger this from happening.
>>
>> Or are you saying you only see the NSAutounbinder stuff in the debugger? If so then - sure, but it's the fact that the progress bar is just sitting there until I move the mouse that alarms me.
>
> Are you saying you're relying on an object being deallocated to change your GUI? You shouldn't be. If you want to close or hide a window, send it a -close or -orderOut: message. If you want to remove or hide a view, remove it from the view hierarchy or send it -setHidden:YES. If its hidden binding is bound to a model or controller property, set that property (on the main thread).
Right, that makes a lot of sense. I can understand the principle of not relying on the dealloc for that sort of thing and on first reading that made complete sense. However, I have now tracked down/remembered the piece of code that was my motivation for taking the approach I did. As always, it turns out the real question is probably not quite the one I originally asked! Can I get your opinion on this workflow? This is how I had previously done things:
- User requests batch processing of data within a folder tree, which will result in between 0 and many separate movies being generated.
- Application allocates a "progress" tracker, subclassed from NSWindowController, in control of a window containing a progress indicator and various other feedback elements.
- This is supplied to separate traversal/parsing code which identifies source data from which movies should be generated.
- For each movie to be generated, the progress indicator is retained in association with a GCD block which will be executed to perform the actual work, added to a serial queue
- Following tree traversal, the application releases its reservation on the progress tracker. If no movies are due to be generated, I had intended this to cause it to be deallocated, at which point I had been closing the window.
If work was queued, this will in due course be executed. The current work block will take control of updating the progress tracker. When it is finished it will release its reservation of the progress tracker. Again, when all work has been completed I intended the retain count to fall to zero at which point it would be deallocated and closed.
My intention with all this was to avoid the need for any "information sharing" between bits of code that I felt should be fairly independent. The application-level code that originally allocates the progress tracker doesn't need to care about what any more specific code wants to do with the progress tracker, it just makes it available to anything that wants to retain it for future use, and then relinquishes any further "personal" interest in that object.
Now, your statement that "[you shouldn't be] relying on an object being deallocated to change your GUI" seems fair, but how would you tackle my scenario here? One possible solution would be to have an intermediary object with no gui/binding/etc of its own, which allocates and owns the progress window and is retained and released by my code as necessary, closing/releasing the window when it is deallocated. In practice, I suspect that would work because that intermediary object "shouldn't" get caught up in any of the deferred autoreleasing that was associated with my original problem. However I am genuinely not sure whether that is just a slightly more indirect way of violating your advice, or whether it is acceptable. I guess I am not sure whether your statement is a generic design principle or a practical rule of thumb for avoiding the sort of issue I encountered.
In my mind retain/release is a way of tracking the interest that my different work packages have on the progress window. If you say you don't like my intermediary object approach then my next proposal will be that I implement a "manual" counter of the number of work packages outstanding... which is really just me reimplementing a parallel retain/release mechanism myself. Is *that* more acceptable, or am I again violating the spirit if not the letter of your statement?
I've rambled a bit here, in my attempts to understand the thinking behind your helpful advice. Would you mind outlining how you would approach this situation yourself?
Many thanks for your comments
Jonny.
_______________________________________________
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