Re: closing a sheet from another controller
Re: closing a sheet from another controller
- Subject: Re: closing a sheet from another controller
- From: Graham Cox <email@hidden>
- Date: Thu, 24 Jun 2010 23:41:54 +1000
On 24/06/2010, at 11:09 PM, John Love wrote:
> I use one of the standard approaches to opening a NSWindowController sheet; that is, my external Controller calls:
>
> [NSApp beginSheet:...]
>
> each of the IB buttons are connected via IBActions that close the sheet via:
>
> [NSApp stopModal]; // sender = NSButton and [sender window] = sheet
> [NSApp endSheet:[sender window] returnCode:theCode]; // calls didEndSelector:
>
> The didEndSelector: looks like:
>
> - (void )sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
>
> which calls:
>
> [sheet orderOut:self];
>
> Fairly standard stuff, but here's the rub. If a error in my app occurs while this sheet is displayed, I want to be able to dismiss the sheet from a external Controller and display an appropriate status message in the sheet's parent window; for example, the external app document (that my application is chewing on) unexpectedly closes. My sheet knows the external Controller that calls +beginSheet: because this external Controller's identity is passed to the method which calls +beginSheet:.
>
> Based on my previous history, there is probably something plainly simple, but I'm just missing it.
John, some time ago I posted a very lengthy explanation of how to encapsulate sheets into a controller. While anyone might argue with the detail, I still strongly believe it's the correct general approach. The above does not appear to follow it.
Your external controller should NEVER call [NSApp beginSheet:...] for a sheet managed by another controller. Instead it should call a method on the second controller like:
-doStuffIDontCareAboutButIfYouDoPutUpASheetHeresAParentWindow:(NSWindow*) parent ohAndThisDelegateMightLikeToKnowWhenYoureDone:(id) delegate;
The second controller can call [NSApp beginSheet:[self window]...] if it likes, but note that the only window it needs to pass is its own.
Once the second controller is fully in charge like this, handling errors arising within its domain becomes straightforward, because the only time external code runs is when it calls it, via its delegate. When it does that, it can wrap such calls in try/catch blocks if necessary. However, exceptions indicate a programmer, not a user, error. So don't use them for flow control - instead return success/failure values.
If you want to put up an error notice while a sheet is showing, consider just using an alert not attached to any window - that's definitely the simplest. If you do need to force the sheet to close so that you can put something else in its place, just put a method on your sheet's controller that safely closes the sheet in a controlled fashion (e.g. by overriding -close to call [NSApp endSheet...]). However if the sheet controller itself receives the passed back success/failure codes from any code it runs, it can simply close itself before passing back any failures to its owner in turn.
Also, you don't need to call [NSApp stopModal], endSheet does that.
The key thing to realise is that if any code other than the internals of the sheet controller are making an assumption about what sort of user interface it's showing (such as the fact that it is indeed running a sheet, as in your posted code, where something external calls -beginSheet:), you've done it wrong.
--Graham
_______________________________________________
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