NSWindow bind load event for control and logic initialization - objective-c

I just started working on an OSX application, first time in objective-c. I need to make a window that will display all the network interfaces available on the computer.
So far
I have an AppDelegate that pretty much does nothing
I have set the Main nib file base name to my main window, which is a xib, header and implementation file
I made my xib window inherit from my class and added the outlets I needed using right-click drag (worked well, I assumed I was correct until then)
The issue
I can't seem either override or bind the load event of the window, where I want to load the text in my label.
I've seen some people use a NSWindowController, but I don't think I need this.
My question
Is it required to have a NSWindowController PLUS a NSWindow class? I feel there are too many files for a single window. I have the xib and two .h/.m files... If it's not required, how can I get notified when the window loads?

The question wether you need NSWindowController(s) or not depends on the complexity of your application.
If your app is only a small utility using a single window, you might get away with setting up your UI in MainMenu.xib and connect it to some IBOutlets in your AppDelegate.
But the above approach gets messy soon when your app becomes more complex. To tame that complexity, you can create dedicated NSWindowController classes (e.g. one per window). Those window controllers could manage a hierarchy of child NSViewControllers to further split up your complexity.
If it's not required, how can I get notified when the window loads?
The default Xcode template should have created an AppDelegate.m file. You can add code to initialize your UI in
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
At this point the window has been fully loaded and
#property (weak) IBOutlet NSWindow *window;
should point to your window instance.

Related

Setting NSWindowController for the root window?

I am playing around with the default XCode template for a cocoa application. By default it has a MainMenu.xib with a window and a menu -- awesome.
I intend to build up my views/subviews in code, so I then create a RootView : NSView and a RootViewController : NSViewController, and bind them up in IB so that my base view in that window is my RootView, controlled by my RootViewController.
Enter my question -- How do I do the same to have a RootWindowController bound to the NSWindow? I had assumed File Owner was the trick, but it's set to NSApplication, which I think is correct. The main goal of NSWindowController in my case is to manage the toolbar based on NSNotifications fired from other services -- is this even the correct design here? I don't think I can do this from my RootViewController since I don't have a window reference, but is that where I should do it instead?
Many times, the application delegate is used as the main/central controller for a non-document-based application. This is a good place. This can be an NSWindowController instance if you like. You can just do away with the existing window in your nib.
Helpful information from the NSWindowController API reference:
You should create a subclass of NSWindowController when you want to augment the default behavior, such as to give the window a custom title or to perform some setup tasks before the window is loaded. In your class’s initialization method, be sure to invoke on super either one of the initWithWindowNibName:... initializers or the initWithWindow: initializer. Which one depends on whether the window object originates in a nib file or is programmatically created.
But if it were me, I wouldn't bother going the NSWindowController route; I'd just add this logic to my app controller (and set it as the app delegate) since this is app-level stuff. No need to add a layer of complexity unless you've got a LOT of main-UI-updating complexity you want to compartmentalize.

XCode 4 - create AppController standard?

I'm using XCode 4, and note that when setting up a new Cocoa Application project, you get an AppDelegate.m and .h file, as well as a .nib (.xib). Using alt-command-return, you get the 3-column editor layout, from which you can control-drag from controls to the AppDelegate.h file to create Outlets or Actions.
My question is, is it recommended to utilise these AppDelegate files to manage your interface controls ie. updating labels, acting on button presses etc. OR is it better to create an AppController class, add an object to the .xib and subclass it to AppController, modifying AppController to mange the controls? If this is the case, what are appropriate uses of AppDelegate?
I would like to say, it is just a matter of development style. What I do is use another class and change the AppDelegate to that class/view and use. Also I do not draw outlets and button on the default window. I make a view and add those as subviews to the mainWindow.

Window-less Cocoa application

I'm a complete beginner in Objective-C and Cocoa.
I would like to create a window-less application, which just shows a NSStatusItem in the system tray. The tray works fine, however, there is one problem.
For some reason my application automatically creates a window for me, which I do not want.
I thought it was caused by the automatic Interface Builder template created when I created the application in Xcode, so I deleted the .nib file from the project. However the window still gets created.
The only lines that contain a reference to the window are in the header:
NSWindow *window;
#property (assign) IBOutlet NSWindow *window;
and in the implementation file:
#synthesize window;
Both were added automatically, I did not write this.
How do I just stop the app from creating a window? I even tried to removing all references to window from the code, including the NSWindow *window, but the window still got created.
My temporary fix right now is to call [window close]; in the application, but surely there is a better way?
My suspicion is that nothing in your code is creating the window. When you create a new Cocoa Xcode application, Xcode sets up an XIB with your interface for you. Open up MainMenu.xib (should be under Resources) in interface builder and delete the window that it throws in by default.
If you don't want to show a window you may consider run your application in background. That will stop the window to appear.
In order to run your application in the background, set YES to "Application is background only" in your app's PLIST file
Return false in your NSDocument subclass' windowNibName method.

Cocoa Application Template - MainMenu.xib - Main Window

When you create a new application in Xcode, it automatically creates a AppDelegate and a MainMenu.xib. The latter also contains the application main window, which is linked to the AppDelegate as an IBOutlet.
What I tried to do is, use a MainWindow from a different xib-file. However, there's absolutely nothing I can do to prevent Cocoa from showing the first window it created in the first place, even if I remove the IBOutlet link and comment it out in the source file and what not...
Hope someone can explain this, as it has been bugging me for a while now...
Whether or not a window in a XIB is shown at launch is not controlled by an explicit code, but instead controlled by the state of the window "freeze-dried" in the XIB.
More concretely, in an inspector of an NSWindow in the Interface Builder, you have the option called Visible at launch under the heading Behavior.
When the Cocoa system loads a nib and encounters a window with this bit on, it just shows it on the screen. It's independent of whether you have IBOutlet or not. You see, it's also the Cocoa system which sets UI objects to IBOutlets when it loads a nib... it can do whatever it wants.

Code Interaction with Quartz Composition

I have a Quartz Composition with a Cube, and X/Y/Z rotation inputs are published.
On Interface Builder I made a QCView and a QCPatchController with the previous Quartz Composition loaded. In QCView the Patch Controller is binded, and the rotation published ports are binded too to three NSSlider, so when I change the value of the NSSlider's then the cube rotates.
All this works fine, but I want to change the rotation values of the cube from the App Delegate on XCode. I tried to change the value of the NSSliders with IBOutlets pointing to them, but this change doesn't apply to the cube, like it does when I change the Sliders directly with my mouse.
What should I instanciate and/or how to access and change this Input_Ports.value throught the CQPatchController?
Thank you very much for reading, i really need help!
It's actually quite simple! The patch controller will accept KVC's setValue:forKeyPath: just fine. (The desired key path will probably look like patch.Input_Ports.value.)
To connect to your patch controller, you'll need to add an outlet to your app delegate. In your app delegate's .h file, add an instance variable IBOutlet NSObjectController* patchController.
IBOutlet doesn't do anything for the compiler, but it signals to Interface Builder that there's an outlet there. Once you've added that line, you'll be able to go back to Interface Builder and control-drag from your app delegate to your patch controller, thus connecting the patchController outlet to the specific instance in your .nib file.
(There is no .h file for QCPatchController, but it's a subclass of NSObjectController, so you can safely declare it as such.)