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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to