Sunday, January 11, 2009

IBOutlet / IBAction Definition

One of the most important concepts of Cocoa (at least to get us started) is the way that Cocoa combines UI and code.
In a Visual Studio project the code that generates the UI is in the same file as the coding itself. 

This is not the case in Cocoa. We have our code completely seperated from the UI, which 
resides in a NIB/XIB file (or several ones).
To get it connected we need to let the code know what interfaces we have and let the UI know what we are working with. We will do this by defining Outlets and Actions in our code, creating an “interface object” in the UI that will be the interface between code and UI and connect the UI elements to that interface.

So what are Outlets and Actions? 
Actions are events which the UI sends to the code when something happens. If you click on a button Cocoa will start the code that you have defined by
  1. linking the button to an action of an “interface object”
  2. calling the method of that action in the code
An Outlet is a link from code to UI. If you want to show or hide an UI element, if you want to get the text of a textfield or enable or disable an element (or a hundred other things) you have to define an outlet of that object in the sources and link that outlet through the “interface object” to the UI element. After that you can use the outlet just like any other variable in your coding.

So let’s get started: 
We’ll create a small app which has a window with a button. As soon as you hit the button, the window will be closed. Not very interesting, but good enough to show how this works.
First of all we will define the outlets. We will only need to call the window to close it, so we only need an outlet  IBOutlet NSWindow *myWindow; The strange thing for me was that we have two definitions for myWindow (IBOutlet and NSWindow)..... but I guess you get used to anything, and that is just the way it goes.
Further we need an action for the time the button gets pressed on the UI. 
-(IBAction)closeWindow:(id)sender;
 
All actions have the IBAction return code (which is the same as void) and the (id)sender as an argument.
Once we saved the file we can switch to the UI in the Interface Builder. Here we add a NSObject whichs Identity we will set to the class in which we added our outlets and actions. Then we create the UI by opening the Window object and dragging a button from the library (Command Shift L) to our window. Now we will set the link from the button to the action. To get this done we need to right click on the button and drag it on the newly created NSObject item. A new popup will appear listing all available actions. You should select the one that you have created. 

After that CTRL-click on the NSObject item. Again a popup will appear listing the outlets that the class has defined. Now we have to drag a line from the outlet (to be precise, from the box right of the outlet) to the window.

Ok, so now we have a class which takes care of the interaction between UI and code; we have our UI, which we attached to the outlets and actions that we defined. So now all what is missing is the code which will do whatever we want when the action gets triggered.
Switch to Xcode and go to the source file to create the method that you want to add. Between the @implementation and the @end enter the method: 

-(IBAction)closeWindow:(id)sender 
     [myWindow orderOut:sender]; 

myWindow is the window of your application (which is a NSWindow instance). The method orderOut hides the window. That’s it!
This way you can also get/set the text of text fields ([textField stringValue]), enable/disable buttons([myButton setEnabled:YES/NO]) or whatever you want.

1 comment:

sean said...

thanks for this very clear definition.