Question

I am very much new to OSX development. Consider this as my first app. I want to display a sheet when a button is clicked on the main window. I am using Nib

Following is my code for .h file

#import <Foundation/Foundation.h>
#import "WebKit/Webkit.h"

@interface MainViewObject : NSObject
- (IBAction)accountButtonPressed:(id)sender;
- (IBAction)cancelSheetButtonPressed:(id)sender;

.m file as follows

#import "MainViewObject.h"
@implementation MainViewObject

- (IBAction)accountButtonPressed:(id)sender {
    [NSApp beginSheet:self.accountSheet
   modalForWindow:[mainWindowView window]
    modalDelegate:nil
   didEndSelector:nil
      contextInfo:nil];

[NSApp runModalForWindow:self.accountSheet];

[NSApp endSheet:self.accountSheet];
[self.accountSheet orderOut:self];
}

- (IBAction)cancelSheetButtonPressed:(id)sender {
// Return to normal event handling
[NSApp endSheet:self.accountSheet];
// Hide the sheet
[self.accountSheet orderOut:sender];
}

When I run the app I get something like this:

http://i.imgur.com/DzJJ6.png

I am stuck and I have no idea what wrong in this. I am not able to get the sheet and the not able to even close the app. I have referred to some examples on internet.

Was it helpful?

Solution

- (IBAction)accountButtonPressed:(id)sender {
    [NSApp beginSheet:self.accountSheet
   modalForWindow:[mainWindowView window]
    modalDelegate:nil
   didEndSelector:nil
      contextInfo:nil];

    [NSApp runModalForWindow:self.accountSheet];

    [NSApp endSheet:self.accountSheet];
    [self.accountSheet orderOut:self];

}

Wow, looking at that, it's no surprise the screenshot looks as it is.

Let's walk through that one line at a time. When you click the Accounts button, you're doing 4 things immediately in succession:

  1. You're telling the application to begin showing the sheet attached to your main window. This is OK, and is actually the only code you want in that accountButtonPressed: method.

  2. Right after beginning that sheet, you tell the application you want to also show that sheet all by itself (not attached to any windows but right in the middle of the screen), in an application-modal fashion, which blocks all other events from being processed in the application. In other words, this line doesn't really make sense. You either show a window as a sheet in a "document-modal" fashion (which only ties up the window that the sheet is attached to) or in an "application-modal" fashion, but not both at the same time. ;-)

  3. Immediately after having just shown the sheet, you tell NSApp to stop showing the sheet. Now, you do want to do this eventually, but dismissing the sheet 0.0005 seconds after having just shown it will likely leave your users a little frustrated.

  4. You now tell the sheet to hide itself. This needs to be done from your didEndSelector: method, which brings us to the problems in your first method.

-

[NSApp beginSheet:self.accountSheet
   modalForWindow:[mainWindowView window]
    modalDelegate:nil
   didEndSelector:nil
      contextInfo:nil];

This is good but read the documentation for beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo: and also the Sheet Programming Topics: Using Custom Sheets. (The Companion guides links at the top of Class Reference pages are especially helpful for learning how to use the APIs in the real world. They were extremely helpful when I was learning).

Specifying nil for the modalDelegate: means you don't have anything that's waiting to be notified about when the sheet has stopped being shown (this happens when you call [NSApp endSheet:sheet]). You also haven't specified the @selector you want called when the sheet is ended. A selector is kind of like a function, aka a "method".

Your code should look something like this:

@implementation MDAppDelegate

- (IBAction)showSheet:(id)sender {
    [NSApp beginSheet:self.sheet
       modalForWindow:self.window
        modalDelegate:self
       didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
          contextInfo:NULL];
}

- (IBAction)cancel:(id)sender {
    [NSApp endSheet:self.sheet];
}

- (IBAction)ok:(id)sender {
    [NSApp endSheet:self.sheet];
}

- (void)sheetDidEnd:(NSWindow *)sheet
            returnCode:(NSInteger)returnCode
               contextInfo:(void *)contextInfo {
    [sheet orderOut:nil];
}
@end

In this example, you click the Show Sheet button, and the sheet starts being shown attached to the main window. In the sheet, there is a Cancel and an OK button, which both call their respective methods. In each of these methods, you call [NSApp endSheet:self.sheet]. This tells NSApp that it should then call the sheetDidEnd:returnCode:contextInfo: method on the object specified to be the modal delegate. In sheetDidEnd:returnCode:contextInfo: you then tell the sheet to hide itself.

EDIT:

Every NSWindow has a "Visible at launch" flag that can be set in Interface Builder. If this flag is set, the window will be visible at the time the nib file is loaded. If it isn't set, the window is hidden until you programmatically show it. Just edit the flag in the nib file like shown:

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top