How to open a new window in a Cocoa application on launch - objective-c

I have created a cocoa application (not document based) and have the default MyAppDelegate class and the MainMenu nib file. I have also created a new nib which contains a window called Splash and a window controller class (NSWindowController) called SplashWindowController.
What I would like is that when the application starts instead of the MainMenu nib window opening I would like to open the Splash window.
I think that I have to create an instance of my SplashWindowController in my AppDelegate class and then instantiate the window and set it to front. However I have tried several things like including a reference to the SplashWindowController.h file in my AppDelegate class and also adding an object to my MainMenu nib and setting its class to be SplashWindowController. But have had no luck with either.
If anybody out there could help me with this one it would be much appreciated as have been at this (what seems like a simple task) for the best part of a day.
Thanks in advance.

You can simply combine both windows into one .xib file.
ExampleAppDelegate.h
#import <Cocoa/Cocoa.h>
#interface ExampleAppDelegate : NSObject <NSApplicationDelegate> {
IBOutlet id splash;
IBOutlet id window;
}
- (IBAction)closeSplashButton:(id)sender;
- (void)closeSplash;
#end
ExampleAppDelegate.m
#import "ExampleAppDelegate.h"
#implementation ExampleAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(closeSplash)
userInfo:nil
repeats:NO];
}
- (IBAction)closeSplashButton:(id)sender {
[self closeSplash];
}
- (void)closeSplash {
[splash orderOut:self];
[window makeKeyAndOrderFront:self];
[NSApp activateIgnoringOtherApps:YES];
}
#end
MainMenu.xib
Add NSWindow (Title: Splash)
Add NSButton to the Splash window
Connect both IBOutlets to the corresponding windows
Connect the button to the corresponding IBAction
Enable 'Visible at Launch' for the splash window (using the Inspector)
Disable 'Visible at Launch' for the main window (using the Inspector)
Result
At launch only the splash window is visible. The splash window automatically closes after 10 seconds. The user can close the splash window directly by pressing the button. The main windows shows up after closing the splash window.

Related

(OSX/Cocoa) How to set controller for main window

I've created a new cocoa application using .xib files (not storyboarded, the app has to be backwards compatible with mavericks/mountain lion) and I would like to have a custom windowcontroller for the main window. Is this possible? I can't seem to find a way to connect the window to my desired custom controller. The window has a reference outlet in AppDelegate, however I need a custom NSWindowController for this window as it doesn't open on application launch. The application launches silently as a menu bar app and the main application is launched via button press in the drop down from the menu bar.
Is there a way to link a controller to the window in the interface builder? Or do I have to do something along the lines of :
wc = [[CustomWindowController alloc] initWithWindowNibName:#"Main"];
Thanks!
Yes, open up Utilities (the right panel) in Interface Builder, and at the bottom click on the Object Library (circle with square in it).
Search for Object (blue cube), and drag it into your Document Outline (the panel on the left inside of interface builder)
From there, select that object you just created, and change the Class in the Identity Inspector to be the window controller you want.
Finally you can go into the Connections Inspector and connect your window to the window outlet
I can't seem to find a way to connect the window to my desired custom
controller. The window has a reference outlet in AppDelegate, however
I need a custom NSWindowController for this window as it doesn't open
on application launch.
Another way:
1) Delete the window in MainMenu.xib. Delete the window property in AppDelegate.m--because you deleted the window, it is no longer relevant.
2) File>New>File>Cocoa Class. Enter a class name, e.g. MainWindowController; select "Subclass of: NSWindowController"; check "Also create .xib file for user interface".
3) Create an outlet in AppDelegate.m:
#import "AppDelegate.h"
#import "MainWindowController.h"
#interface AppDelegate ()
#property (strong, nonatomic) MainWindowController* windowController;
#end
4) Declare an action in AppDelegate.h:
#interface AppDelegate : NSObject <NSApplicationDelegate>
-(IBAction)launchWindow:(id)sender;
#end
and implement it in AppDelegate.m:
- (void)launchWindow:(id)sender {
[self setWindowController:[[MainWindowController alloc]
initWithWindowNibName:#"MainWindowController"]];
[[self windowController] showWindow:nil];
}
5) In MainMenu.xib, hook up the Menu Item to the launchWindow() action: control drag from the Menu Item to the AppDelegate object and select launchWindow.
Create the controller and make it extend from NSWindowController.
In your xib file select the File's Owner and set it to your custom class.
Select your NSWindow and connect it to the File's Owner.
To open the window:
In your .h:
#property (strong, nonatomic) YourWindowController *yourWinController;
In your .m:
self.yourWinController = [[YourWindowController alloc] initWithWindowNibName:#"YourWindowController"];
[self.yourWinController showWindow: nil];

cocoa windowDidEnterFullScreen not being called

I'm writing a Cocoa application which should work in fullscreen mode. I would like to detect the user setting the application window to fullscreen mode.
In Xcode,
in the Attributes Inspector, Full Screen value is "Primary Window"
in the File Inspector, Use Auto Layout is unchecked
the view of the main window has Autoresizes Subviews unchecked
I'm making the AppDelegate an NSWindowDelegate like this in AppDelegate.h
#interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>
and have a method like this in AppDelegate.m
-(void) windowDidEnterFullScreen:(NSNotification *)notification
{
vuMain.view.frame = NSMakeRect(0, 0, window.frame.size.width,
window.frame.size.height);
NSLog(#"AppDelegate - windowDidEnterFullScreen");
}
But this method is not getting called as there is no NSLog output. A watch set in the method does not get reached.
What am I doing wrong? What am I missing?
Please help! I'm rather new to Cocoa and am struggling for one full day with this.
Thanks
You need to actually make the AppDelegate the window's delegate. You either have to connect the window's delegate outlet to the AppDelegate in the NIB, or you need to set the window's delegate property programmatically.

How can I set a menu item click to respond to IBAction from another class?

I'm pretty new to XCode/Objective-C/Cocoa. I want to implement a settings window for my app.
I have a MainMenu.xib which also holds my main Window. From the menu, I want to open a settings window. I created Settings.xib and appropriate .h and .m files to hold what that window would do.
Settings.h:
#import <Cocoa/Cocoa.h>
#interface Settings : NSWindowController <NSApplicationDelegate>
-(IBAction)openSettings:(id)senderId;
#property (nonatomic, retain) Settings *thisWindow;
#end
Settings.m:
#import "Settings.h"
#implementation Settings
- (void)windowDidLoad {
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
// open preferences window
- (IBAction)openSettings:(id)senderId
{
_thisWindow = [[Settings alloc] initWithWindowNibName:#"Settings"];
[_thisWindow showWindow:self];
}
#end
I dragged my Preferences menu item to first responder, and selected openSettings: from there.
However, the item is still disabled and I'm pretty sure it's because I did nothing to link the Settings interface to my MainMenu.xib, which works with AppDelegate.h/m.
How do I make this work? All other solutions I found didn't quite work for me.
If I understand you clear you want to store your MainMenu and MainWindowController in a two separate classes.
Open your main menu nib-file. Remove window from the object tree.
Check in Project Settings -> General -> Main interface is still your MainMenu (without .xib-extension).
Create (implement) your custom MainWindowController class (with a nib-file may be).
Open AppDelegate class. In - (void)applicationDidFinishLaunching:(NSNotification *)aNotification method create an instance of main window controller class, show the window
Use this code below
MainWindowController *controller=[[MainWindowController alloc] initWithNibName:#"MainWindowController"];
[controller showWindow:nil];
[controller.window makeKeyAndOrderFront:nil];
Here it is.
Okay so in your mainwindowcontroller, declare a property of type NSWindowController *settingsWindow. Init it with the corresponding xib.
Then create a method called -(void)openSettings, with one line [self.settingsWindow showWindow:self];
Then also in your mainWindowController initialization, init a NSMenuItem, and set it's action to openSettings. Then add that NSMenuItem to the Mainmenu where you'd like programmatically, like this
//mainMenu is your application's menu-- if you switched index to 1 it would be the 'File' menu
NSMenu *mainMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu];
[mainMenu insertItem:newItem atIndex:4];
I ended up using my AppDeleate.m to open the dialog instead. I linked the menu button to the AppDelegate object in the interface builder, and used openSettings:. Here's how it looks:
// open preferences window
- (IBAction)openSettings:(id)senderId
{
_settingsWindow = [[Settings alloc] initWithWindowNibName:#"Settings"];
[_settingsWindow showWindow:self];
}
In AppDelegate.m, instead of Settings.m.

Is it possible to have a custom NSWindowController on launch?

In this answer is said it is possible to have a custom NSWindowController by removing the window from MainMenu.xib and instantiating the window controller 'manually' from applicationDidFinishLaunching:. But it also says:
To stop the default window from showing I just delete it. There's probably a better way but I don't know that.
Is there a better way? What is that better way, should it exist? Is it considered 'normal' practice to get your own window controller?
To do this, you would usually subclass NSWindowController and change the File's Owner class to your WindowController subclass in the nib.
EDIT:
If you aren't doing a document-based app, and just want an NSWindowController of your own to do on-demand loading of Nibs (completely reasonable), then you'd delete the window from your nib and instantiate an NSWindowController subclass programmatically, using it explicitly to do your window loading...
#implementation MyApplicationDelegate {
MyWindowControllerSubclass *windowController;
}
-(void)applicationDidFinishLaunching:(NSNotification *)notification {
windowController = [[MyWindowControllerSubclass alloc] initWithWindowNibName:#"MyWindowNib"];
[windowController showWindow:nil];
[windowController.window makeKeyAndOrderFront:nil];
}
I was running into the same issue and I want to show you my own solution.
Create a normal Cocoa Application (not Document Based)
Go to MainMenu.xib an delete the Window
Go ahead and create a new file, User Interface -> Window
After that create a subclass of NSWindowController
Open the just created xib file and set the Custom Class in the Identity inspector to the just created subclass of NSWindowController
Right click on File's Owner and connect the window property to the actual window
Now go to the AppDelegate an create an instance variable that holds you CustomWindowController
Last thing you have to do is instantiate your CustomWindowController self.customWindowController = [[AccountWindowController alloc] initWithWindowNibName:#"CustomWindow"]; and show the Window [self.customWindowController showWindow:nil] in - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
Here is an example project https://www.dropbox.com/s/ft3t7w72806tnoe/CustomWindowController.zip
I actually found another way: NSWindowController has the method -initWithWindow:. Because the App Delegate has a property window which is linked to the window from MainMenu.xib on startup, it was easy to link it to my WindowController:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
MyWindowController *wincon = [[MyWindowController alloc] initWithWindow:window];
}
I have yet to research this, but I don't get any errors.

Swapping views - NSWindowController and NSViewController(s)

I'm very new in Mac OS programming. At the moment I'm trying to create simple measurement application which will have one window with the toolbar at the top and the appropriate view in the bottom. Clicking button in the toolbar should result in switching view below it - e.g. clicking on the "Connection" button will show with connection settings, "Measurements" will show current data from the device.
The problem is - I don't know how to handle swapping views, maybe in other words - something I know but not exactly...
I found similar discussion here: NSViewController and multiple subviews from a Nib but there is no answer how to create NSWindowController and how to assign it to the Main window. Because I guess it is necessary to create NSWindowController to be able to swapping views. If I'm wrong, please correct me.
So I'm creating new project (called Sample here) and there is SampleAppDelegate.h file, which looks like:
#interface SampleAppDelegate : NSObject <NSApplicationDelegate> {
#private
NSWindow *window;
}
#property (assign) IBOutlet NSWindow *window;
#end
There is window ivar, which holds the only one window, created from the MainMenu.xib (as I think).
So how should I create NSWindowController for the window from the SampleAppDelegate?
Should I just create my WindowController subclass and in the function
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
of the SampleAppDelegate like this:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
MyWindowController *wc = [[MyWindowController alloc] initWithWindow:self.window];
[wc showWindow:self];
self.myWindowController = wc;
[wc release];
}
I'll be very grateful for any hints and help.
Marcin
You shouldn't need an NSWindowController to do view swapping, NSWindowController used (I think) just when you need multiple toplevel windows.
You can just subclass NSViewController for each type of view that you want, put each view into a nib, and call -(NSView *)view when you need a view to put into the bottom part of the window. You should be able to just add it to the window like normal, or put it in an NSBox by using setContentView:view
For your two views you'd create MeasurmentsViewController and a ConnectionViewController. Then you'd create your views in MeasurementsView.nib and ConnectionView.nib, and use those nibs to initialise your view controllers.
Then in your main window, if you were to put an NSBox, if you wanted to put the MeasurementsView into it
NSView *measurementsView = [measurementsViewController view];
[boxAtBottomOfWindow setContentView:measurementsView];
and to put the ConnectionView into it
NSView *connectionView = [connectionViewController view];
[boxAtBottomOfWindow setContentView:connectionView];