Hi, I have a simple single-window Cocoa app (not document-based). When
the app starts I would like bring up a sheet asking for a password.
Once the password is valid, the sheet should disappear and the
application can be used by the user.
Attempt 1: using NSApplication's
beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:
This is what I'm currently using. The problem is that once the sheet is
displayed on screen, program flow immediately proceeds. In other words,
it doesn't wait for the password to be entered and the sheet to be
closed.
Attempt 2:
Searching through the docs I found that I could use this for tighter
control over the event loop:
NSModalSession session = [NSApp beginModalSessionForWindow:theWindow];
for (;;) {
if ([NSApp runModalSession:session] != NSRunContinuesResponse)
break;
}
[NSApp endModalSession:session];
This code does work, and can be used to wait for the sheet to be closed
but unfortunately it uses 80% of CPU (as I expected it would).
Attempt 3:
Trying to reduce the amount of CPU used, I did the same thing as
Attempt 1, but added locking (using NSLock) to wait on sheet closing.
That was dumb because it would put the same thread to sleep that was
supposed to clear the lock at some point.
Attempt 4:
Finally, I gave up on sheets and used a Panel instead with
NSApplication's runModalForWindow:. This does wait for the panel to be
closed (actually waits for stopModal) without any contortions on my
part. But damnit, I really want a sheet :-)
So how do I get a sheet to behave like a panel with runModalForWindow:
in terms of only returning when the sheet is closed?
Thanks for any insight.
Chris
Patrick Machielse - 23 Oct 2005 00:02 GMT
> Hi, I have a simple single-window Cocoa app (not document-based). When
> the app starts I would like bring up a sheet asking for a password.
> Once the password is valid, the sheet should disappear and the
> application can be used by the user.
[]
> Attempt 2:
> Searching through the docs I found that I could use this for tighter
[quoted text clipped - 9 lines]
> This code does work, and can be used to wait for the sheet to be closed
> but unfortunately it uses 80% of CPU (as I expected it would).
Why not +[NSThread sleepUntilDate:...] in the loop?
[]
> So how do I get a sheet to behave like a panel with runModalForWindow:
> in terms of only returning when the sheet is closed?
Does -[NSAlert
beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo] do
what you need?
patrick
Michael Ash - 23 Oct 2005 11:11 GMT
> Hi, I have a simple single-window Cocoa app (not document-based). When
> the app starts I would like bring up a sheet asking for a password.
> Once the password is valid, the sheet should disappear and the
> application can be used by the user.
[snip]
> So how do I get a sheet to behave like a panel with runModalForWindow:
> in terms of only returning when the sheet is closed?
You do not.
Sheets by their very nature, both from a GUI point of view and a code
point of view, are non-blocking. Getting them to act otherwise is going to
be a giant pain and may not be reliable.
Just rearrange your code so that the "after password" stuff runs in your
sheet's didEndSelector. Of course, the "just" may be a little
understating the difficulty, but it shouldn't be that hard. Any relevant
data can be stored as an instance variable, or passed through the
contextInfo:.
If for some reason this is impossible, use a real modal panel instead of a
sheet.

Signature
Michael Ash
Rogue Amoeba Software
Doctor Captain - 24 Oct 2005 08:40 GMT
>> Hi, I have a simple single-window Cocoa app (not document-based). When
>> the app starts I would like bring up a sheet asking for a password.
[quoted text clipped - 20 lines]
> If for some reason this is impossible, use a real modal panel instead
> of a sheet.
Thanks Michael,
Just getting confirmation that what I was trying for isn't really
feasible is really helpful! I thought about putting my after-password
stuff in the sheet's didEndSelector, but didn't like the amount of
extra state I'd have to keep track of (e.g. what if I wanted to have
the user re-enter the password after a certain period of inactivity -
then the post-password "wake up" would be different than the first time
after the application has started). I'll follow your advice and stick
with the modal panel.
Patrick, thanks for your comments too.
Chris