Not Able to Quit App after Application Modal Dialog created

Discussion in 'Mac Programming' started by petron, Dec 19, 2009.

  1. petron macrumors member

    Joined:
    May 22, 2009
    Location:
    Malmo, Sweden
    #1
    Hi,
    I have a NSDocument application.

    Recently I added an Modal Dialog at the start up and a side effect appeared.

    The Modal Dialog appear and when entering what needed there it is closed, and the main application take over the control. The side effect is that I am not able to close the application after the Modal Dialog has been opened and closed. CMD-Q does not work, In the menu the Quit command is grayed out.

    If I do not activate the Modal Dialog there are no problems with the Quit.

    Dialog controller looks like this:

    Code:
    #import "DialogController.h"
    @implementation DialogController
    
    - (id)init
    {
        [super init];
        return self;
    }
    
    - (NSString *)showStartUpDialog:(NSWindow *)window
    {
        if (!myStartupDialog) {
            [NSBundle loadNibNamed:@"MyStartUpDialog" owner:self];
        }
        [NSApp beginSheet: myStartupDialog
           modalForWindow: window
            modalDelegate: nil
           didEndSelector: nil
              contextInfo: nil];
        [NSApp runModalForWindow: myStartupDialog];
        // Dialog is up here.
        [NSApp endSheet: myStartupDialog];
        [myStartupDialog orderOut: self];
        return logFileName;
    }
    
    - (IBAction)endDialogSheetAndCreate:(id)sender
    {
        logFileName = [fileNameField stringValue];
        if ([logFileName length] <= 0) {
            logFileName = nil;
        }
        [NSApp stopModal];
    }
    
    - (IBAction)endDialogSheetAndCancel:(id)sender
    {
        logFileName = nil;
        [NSApp stopModal];
    }
    @end
    
    Any tip out there ?

    Thanks in advance.
    /petron
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    This is wrong. See the "Implementing Initializers" section of this doc:
    http://developer.apple.com/mac/libr...nceptual/ObjectiveC/Articles/ocAllocInit.html


    Code:
        [NSApp beginSheet: myStartupDialog
           modalForWindow: window
            modalDelegate: nil
           didEndSelector: nil
              contextInfo: nil];
        [NSApp runModalForWindow: myStartupDialog];
    
    This code is wrong. You must choose either a modal sheet or a modal dialog, not both. A modal sheet would be attached to a window and be document-modal. A modal dialog would be free-standing and be application-modal. I can't tell which one you intend.


    Code:
        [NSApp endSheet: myStartupDialog];
        [myStartupDialog orderOut: self];
    
    If the earlier modal-beginning code weren't wrong, then this would be wrong. You'd have to end the modalities in the reverse order in which you began them.


    Code:
    - (IBAction)endDialogSheetAndCreate:(id)sender
    {
        logFileName = [fileNameField stringValue];
        if ([logFileName length] <= 0) {
            logFileName = nil;
        }
        [NSApp stopModal];
    }
    
    - (IBAction)endDialogSheetAndCancel:(id)sender
    {
        logFileName = nil;
        [NSApp stopModal];
    }
    
    I can't tell if these are right or wrong or somewhere in between.


    If you aren't working from a book, a tutorial, or a working example, you probably should be. You should also read the Companion Guide on working with sheets, and read about the differences between document-modal and application-modal in Apple's Human Interface Guidelines. There are links to all those docs in the NSApplication class reference:

    http://developer.apple.com/Mac/libr.../NSApplication_Class/Reference/Reference.html
     
  3. petron thread starter macrumors member

    Joined:
    May 22, 2009
    Location:
    Malmo, Sweden
    #3
    Hi Chown33,
    Thanks for the comments.

    Part 1. Good point, You are right, the init part is not good one, but it does not make much harm neither. In my case I can drop the whole init part since I do not have any thing to add into the init part. I do not need to override it.

    Part 2. I have to admit that I am confused regarding the other comments.

    Based on the doc from Apple:

    http://developer.apple.com/mac/libr...eptual/Sheets/Tasks/UsingAppModalDialogs.html

    My code is very similar. It may be wrong but It would be good to know what do you mean by your comments. I may misunderstood the DOC and mixed up things.

    I will try to go through it again and see if I missed the point.
    If you compare my code with the Apple's code there are not much differences.
    For example The sequence of ..endSheet.. and ..orderOut.. are the same.

    Could you please clarify your statement.

    I will read the article again and maybe I will understand your comments better.

    B.R.
    /petron
     
  4. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #4
    hm, that is odd code by Apple. I've never seen beginSheet and runModalForWindow used together. It's either one or the other.

    Anyways, to run a sheet you only need the beginSheet method. To close the sheet, use
    Code:
    [NSApp endSheet:theWindow];
    [theWindow orderOut:nil]; // or some other variation
     
  5. petron thread starter macrumors member

    Joined:
    May 22, 2009
    Location:
    Malmo, Sweden
    #5
    Hi Kainjow,

    I' am reading the documentation right now. I did not found any good solutions, but thanks for comments.

    I would like to understand what is going on... other wise i will be doing the same problem again and again.

    I tried your tip, but it even works worse... No dialog shows up.

    /piotr
     
  6. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #6
    Can you post your updated code? And are you getting any messages in the console?
     
  7. petron thread starter macrumors member

    Joined:
    May 22, 2009
    Location:
    Malmo, Sweden
    #7
    Hi Kainjow,

    Not much to add, Since you mentioned that you did not seen this contraction with both beginSheet and runModalForWindow, I tried to remove the runModalForWindow. But then I do not get the dialog window up.

    As mentioned before in the original code:
    The dialog Window shows up.
    The return string get updated when pressing create,
    The return string gets nil when pressed cancel.
    The dialog ends its live
    The mainNSDocument window takes over the control, but what seems wrong that the possibility to quit app is gone. Seems like I have modality problem.
    Maybe some hot the stopModal does not work?

    If you look at the example from the Apple Docs I did in a very similar way, so the construction is not taken from the air. Though I made something wrong since I still do not understand the whole process.

    Thanks for bearing with me...
    B.R.
    /petron
     
  8. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #8
    I may have been too quick to call the code wrong. Still, parts of it seem ill-advised at best.

    The description accompanying Apple's code makes it clear that this should display a sheet attached to a document window, but the behavior will be app-modal. That's very odd. It's not a normal app-modal dialog, and I don't recall ever seeing an app-modal sheet in any app I've used. Nor have I ever coded a sheet so it acts app-modal. I see no advantage to an app-modal sheet, as opposed to the more common free-standing app-modal dialog window. I think an app-modal sheet would just lead to confusion.

    When I've used a free-standing app-modal dialog via runModalForWindow, I invariably call close() on the dialog's NSWindowController, after the modal session has ended. I do not call orderOut on the window.

    I have been in situations where a document-modal sheet must be hidden because in that particular case the hiding wasn't done automatically, at the time I wanted it done. In those cases I call orderOut on the sheet to dismiss it.

    Instead of removing the runModalWindow code, I suggest removing the beginSheet code and sticking to a plain ordinary free-standing app-modal dialog window. I also suggest calling close on the controller, rather than orderOut on the window.

    The problem may not even be in the posted code. It may instead be related to when and where the dialog is presented, i.e. exactly when showStartUpDialog is called. If that's done in the wrong place, then the app may end up in the wrong state. I would put the call in applicationDidFinishLaunching. I have made mistakes that caused the Quit menu-item to be left disabled. There was no single cause I can point to; it depends on what's happening and when.

    Finally, it's difficult to investigate the problem or any possible solutions because there isn't enough code to compile, and we'd have to guess what all the missing parts are. Please consider posting the project with its source and xib files. If you can't post the entire project, consider stripping out all except the parts that show the problem and posting that. Obviously, do this on a duplicate of your original project.
     
  9. petron thread starter macrumors member

    Joined:
    May 22, 2009
    Location:
    Malmo, Sweden
    #9
    Hi Chown33
    Thanks for the comments .
    I am on the run and have the access to the internet only via
    iPod touch for a while.
    I will start to investigate your ideas when back to my place and
    my Mac
    merry Xmas
    /petron
     
  10. petron thread starter macrumors member

    Joined:
    May 22, 2009
    Location:
    Malmo, Sweden
    #10
    Hi to helpers..

    The problems is solved now. I wanted to publish the project but I wanted to make a simple and small one. With a main App and a modal dialog window.

    When creating and coping the code I discovered the problem.

    The problems has been introduced when creating the second XIB file. I wrongly created the Dialog.XIB using the Application XIB template in the XCODE. One should obviously use either Empty XIB template or Window XIB template.

    The application works perfect with published code. The exception is the init method that has been changed.

    Thanks for bearing with me.
    /petron
     

Share This Page