I'm trying to get a Login Window to display as a sheet from my MainWindow, but whenever I try to implement the AppKit methods an error always pops up for various indistinguishable reasons.
None of the online guides out there are working, when i apply their code / adapted classes to my own project they never work.
Most of the guides are heavily outdated, including the Apple Documentation. And none of them seem to be compatible with Automatic Reference Counting. Or the Xcode 4 interfaces.
Would someone be able to detail for me in full a guide, for the simplest way of displaying a sheet following a button press on the MainWindow.
Feel free to ask for more information if you need it.
Tutorial for Xcode 4
Create new project and add the following to AppDelegate.h
and AppDelegate.m
.
AppDelegate.h
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate> {
IBOutlet NSPanel *theSheet;
}
@property (assign) IBOutlet NSWindow *window;
@end
AppDelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize window = _window;
- (IBAction) showTheSheet:(id)sender {
[NSApp beginSheet:theSheet
modalForWindow:(NSWindow *)_window
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
}
-(IBAction)endTheSheet:(id)sender {
[NSApp endSheet:theSheet];
[theSheet orderOut:sender];
}
@end
Open the MainMenu.xib
.
Use the existing NSWindow
.
Make it visible using the following button:
Create one new NSPanel
.
Add the appropriate NSButtons
.
Connect Close
to the App Delegate
.
And select endTheSheet
.
Connect Open
to the App Delegate
.
And select showTheSheet
.
Connect the App Delegate
to the new NSPanel
.
And select theSheet
.
Select the NSPanel
and disable Visible At Launch
.
(Essential step!)
Now hit run and enjoy the result:
Things have changed in SDK 10.10 - the calls are simpler to understand I think. A parent window is in charge of launching a child NSWindow as a sheet - and then you pass this child NSWindow to NSApp to run modally. Then do the opposite to unwrap.
Displaying sheet
To display the sheet instead of calling:
[NSApp beginSheet:theSheet
modalForWindow:(NSWindow *)_window
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
You now call on the parent window:
(void)beginSheet:(NSWindow *)sheetWindow
completionHandler:(void (^)(NSModalResponse returnCode))handler
And then to run the sheet as in modal loop, you also have to call NSApp with:
- (NSInteger)runModalForWindow:(NSWindow *)aWindow
Closing Sheet
To close the sheet, call on the parent window:
- (void)endSheet:(NSWindow *)sheetWindow
Which causes the completionHandler from the above call to fire, - in which you can put a call to stop running the modal window by calling NSApp with:
- (void)stopModalWithCode:(NSInteger)returnCode
Full example
@implementation AppDelegate
@synthesize window = _window;
- (IBAction) showTheSheet:(id)sender {
[_window beginSheet: theSheet
completionHandler:^(NSModalResponse returnCode) {
[NSApp stopModalWithCode: returnCode];
}];
[NSApp runModalForWindow: theSheet];
}
-(IBAction)endTheSheet:(id)sender {
[_window endSheet: theSheet];
}
@end