Modal sheet not working in applicationdidfinishlaunching? - xcode

I'm trying to get a sheet to display modally when the app finishes launching. If I place the code in a generic action and execute it somewhere after app launch, it works as desired and the sheet drops down nicely. If I take the same code and place it in applicationdidfinishlaunching, the sheet displays as a separate window (which is not what I need).
[NSApp beginSheet:settingsWindow
modalForWindow:[NSApp keyWindow]
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
[NSApp runModalForWindow:settingsWindow];
[NSApp endSheet:settingsWindow];
[settingsWindow orderOut:self];
The visible at launch option is disabled. Grateful for any suggestions. I also tried it in awakefromnib with the same incorrect result.
Edit: Using [self performSelector:#selector(someAction:) withObject:self afterDelay:0.5]; where the contents of someAction are as above, yields the correct result. Why is this?

NSApp's beginSheet: modalForWindow: modalDelegate: didEndSelector: contextInfo: and endSheet: are deprecated in OS X 10.10. You should instead use beginSheet: completionHandler: on NSWindow instance to show the sheet window modally.
NSWindow *mainWindow = [NSApp windows][0];
[mainWindow beginSheet:settingsWindow completionHandler: nil];
By the way, does the [NSApp keyWindow] return an instance in didFinishLaunching?

Related

AppDelegate stops getting windowDidResize

I have a single window cocoa app. In appDidFinishLaunching I have [[self window] setDelegate: self]. When the app first launches windowDidResize gets called without issue. After a few actions, it doesn't get called again. I haven't closed the window or called anything to do with the window. Haven't changed the delegate, window or self. If I drop in a few
NSLog(#"Window: %# Self: %# Delegate: %#", [self window], self, [_window delegate]);
it's exactly the same before and after it stops working. I do do a fair bit with the notification center, posting and acting on my own notifications but delegates don't rely on notification center, correct? Any tips on figuring out what's happening here?

How to make it from top ? (Cocoa sheet)

I have implemented my sheet (NSPanel) with the following method:
- (void)showInWindow:(NSWindow *)mainWindow {
if (!finestra1)
[NSBundle loadNibNamed:#"XibName" owner:self];
[NSApp beginSheet:finestra1 modalForWindow:mainWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
[NSApp runModalForWindow:finestra1]; //This call blocks the execution until [NSApp stopModal] is called
}
The sheet is appearing in the middle of my screen, how to attach it to the top of my main window and make it appear with a "slide down" effect instead?
Thanks in advance.
Have you tried simply removing the -runModalForWindow: line?
The way I was taught, the sheet you're presenting should be an NSWindow, not an NSPanel.
Let me know if you'd like me to upload a simple demo project.

Sheets are not displaying properly on OSX

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.
- (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:
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.
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. ;-)
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.
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:

Is it possible to force control to an NSWindowController Subclass?

I am creating a cocoa application and I am loading a preference window with a NSWindowController.
When the user selected the prefs button and the preference window opens
I want the application to force the user to finish what they are doing with the newly opened window controller before going back to the application in the background.
Is there anyway to block out whats happening in the background and force the user to complete there interactions with the foreground?
Thakns
Perhaps this works? Create a subclass of the HUD window and implement
- (BOOL)resignFirstResponder {
if (userMayLeave) return YES;
return NO;
}
You can use the following method to achieve this and display your window as a modal:
[[NSApplication sharedApplication] runModalForWindow:aWindow];
Then you need to use one of the following methods in your modal window in order to dismiss it:
[[NSApplication sharedApplication] stopModal];
[[NSApplication sharedApplication] abortModal];
[[NSApplication sharedApplication] stopModalWithCode:anInteger];

Why the splash window can’t show before the App launch?

I want to show a splash Screen before the App lunch. First I make the SplashWindow subclassing the NSWindow, the code is :
- (id)initWithContentRect(NSRect)contentRect
styleMask(unsigned int)aStyle
backing(NSBackingStoreType)bufferingType
defer(BOOL)flag {
self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
[self setBackgroundColor:
[NSColor clearColor]];
[self setLevel: NSStatusWindowLevel];
[self setAlphaValue:1.0];
[self setOpaque:NO];
[self setHasShadow: YES];
return self;
}
and then in the awake from nib in the main app controller:
loadWindow = [[NSWindow alloc] initWithContentRect:[loadWindow frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
[loadWindow setContentView:theView];
[loadWindow setHasShadow:YES]; [
loadWindow setLevel:NSStatusWindowLevel];
[loadWindow makeKeyAndOrderFront:self];
and then I let the loadWindow closed after 3 secondes, I used the method [loadWindow orderOut:self], but when the splash window closed , the mainwinow didn't show . what am I missing? My App is a multi_Documents . and in the mainMenu.nib there was one window(loadwindow),in IB I have connected up the loadWindow outlet in the main controller. I have also connected the view and image. and I changed another way : in the delegate method:applicationWillFinishLaunching: I orderFront the loadWindow , in the method:applicationDidFinishLaunching: I orderOut the loadWindow after 3 seconds, but the mainWindow didn't show too.Somebody can give some advice or codes the result the problem? Thank you very much!
Answer to title: Because your app isn't running yet. An application that isn't running can't do anything.
Serious answer to question:
First, you don't need to subclass NSWindow.
Second, you aren't instantiating your subclass, you're instantiating NSWindow. That's why you're not getting your subclass's behavior. (And this is what you should be doing, since you don't need the subclass.)
Third, you're trying to ask a window that doesn't exist yet for the frame you'll use to create it. loadWindow is nil until after you create something and store it there.
Fourth, because you are asking nil for its frame, you are getting a garbage rectangle back. Then you create a window with this garbage rectangle. Unsurprisingly, when you put this window on the screen, it appears in a random position (probably off-screen) with a random size (probably either too large to create or negative).
Fifth, what makes you think that telling a window to order out would cause some other window to order in? How is it supposed to know what window to order in?
Leaving aside the undeniable reality that the very existence of a splash screen punishes the user for using your application, you should be using NSWindowController to load the window and to do your set-up such as setBackgroundColor: and setLevel:. And in your timer method, where you order out the splash window, you must also explicitly order in the main window.
I don't see anything that would make another window show in the code you posted. Why don't you try sending your main window makeKeyAndOrderFront:?

Resources