SimpleTutorial

Index
This is an extremely simple Cocoa# tutorial that creates a Mac OS X application, composed of a simple form with a textfield and a button that changes the text in the textfield.

Contents

Authors

Requirements

Apple's Developer Tools
If these aren't already installed on your computer, you can download and install the latest version from http://developer.apple.com/tools/download/.
Mono and CocoaSharp
CocoaSharp is now included with the Mono packages, so you can download and install a recent version from http://www.mono-project.com/Downloads. At the time this was written, the current version is "1.2.3.1_0".

Starting Off

Building The NIB

The first thing to do is create a NIB file for use with the application. A NIB file is so much easier to use than creating the entire window and controls via code.


Click to zoom in
  1. Open "Interface Builder" from /Developer/Applications.
  2. From the "Starting Point" dialog select "Cocoa" and then "Application". If the Starting Point dialog doesn't appear select "New" from the "File" menu.
  3. Save the file as "Main.nib"
  4. You should now see four windows, titled "Cocoa-Controls", "Window", "Main - MainMenu" and "Main.nib". Drag an "NSButton" and "NSTextField" from the "Cocoa-Controls" windows to the "Window".
  5. In the "Main.nib" window, that has five segments named Instances, Classes, Images, Sounds, and Nibs click on Classes.
  6. Scroll all the way to your left, Right Click on the "NSObject" and select "SubClass NSObject".
  7. Name the new object "ApplicationController".
  8. Right Click on "ApplicationController" and select "Instantiate ApplicationController". This will make the Instances tab of the window visible. You should now see a blue cube with the name of "ApplicationController".
  9. Click on the Classes tab again, find "ApplicationController", and Right Click on it, select "Add Outlet".
  10. This will make the Info Window visible (if it wasn't already). Add a new outlet named "textField1", set the type to "NSTextField". Add another outlet named "mainWindow" and set type to "NSWindow". In the same window click on the "Actions" tab and add an action named "buttonClick".
  11. Go back to the Instances tab, hold the Ctrl key down, click on "ApplicationController" and drag to the "NSTextField". After you do this the Info window will appear (if not already visible) and will be on the Outlet's page. Make sure that you highlight the outlet named "textField1" and then hit "Connect".
  12. Ctrl Click and drag from the "NSButton" to the "ApplicationController" The Info window will appear, if the "buttonClick" action is not highlighted, go ahead and highlight it and then click connect.
  13. Ctrl Click and drag from "File's Owner" to "ApplicationController", connect to the "delegate" Outlet.
  14. Ctrl Click and drag from "ApplicationController" to "Window" instance (located in Instance tab). Assign this to outlet "mainWindow".
  15. Save the file.

Actions vs. Outlets

Actions: Actions are like events. Creating an action in a nib will allow you to assign it to any control that has event capabilities. Note: You can also assign actions via code (ie "button1.action = buttonClick")

	Actions are connected by Ctrl Clicking/Dragging from 
	the Interface Element to the Controller Object.

Outlets: Outlets are a way to tie objects in the GUI to variables in code. If you don't have the outlet tied to anything then you can't use it. It's a way to tell the Code what variable is pointing to what interface element.

	Outlets are connected by Ctrl Clicking/Dragging from 
	the Controller Object to the Interface Element.

The Code

main.cs

The main.cs file is the entry point to the app. We split this off from the actual ""ApplicationController"" so that we can keep track of things easily.

using System;
using System.Runtime.InteropServices;
using Cocoa;

class MainClass {
	public void Run() {
		Application.Init();
		Application.LoadNib ("Main.nib");
		Application.Run();
	}
	
	static void Main(string[] args) {
		MainClass main = new MainClass();
		main.Run();
	}
}

The important thing to consider here is the "Application.LoadNib()" line. Make sure it's loading the proper NIB file.

applicationcontroller.cs

The applicationcontroller.cs is the main interface handling point. This is where all the GUI elements are connected and defined.

using System;
using System.IO;
using System.Collections;
using Cocoa;

[Register("ApplicationController")]
public class ApplicationController : Cocoa.Object {
        
	[Connect]
	public TextField textField1;
        
	[Connect]
	public Window mainWindow;

	protected ApplicationController(System.IntPtr a) : base(a){}
        
	//Form.Load Event
	[Export("applicationWillFinishLaunching:")]
	public void FinishLoading(Notification aNotification) {
		textField1.Value = "Form Loaded";
	}

	[Export("buttonClick:")]
	public void buttonClick(object sender) {
		textField1.Value = "Button Pushed";
	}
        	
}

Connect/Register

I'm not sure what the technical explanation for this is, but this is the part that connects the variable you define to the object from the nib. You can have interface elements that do not have a local variable in the code, but you cannot connect local variables to non existent interface elements. Doing so will cause the app to crash on launch. For every interface element that you want to be able to access via code, you will need to create a new variable of the proper type and make sure that you use the "Connect" statement above it.

The Register statement above the beginning of the class connects this class to the "ApplicationController" from the NIB.

Export

The export tag is the one that ties local events to the events declared in the NIB. You can assign these events to an interface object a couple of ways. You can Ctrl Click and drag from the interface element to the controller class, or you can define it via code. The NIB method is normally easiest but some interface elements don't like it.

In the above example you can see that we have exported "buttonClick:" to my local buttonClick handler. The "applicationWillFinishLaunching:" event is generated by the (app/main window). Think of it like the FormLoad event in winforms (as far as I can tell).

Compiling

You could just type the necessary commands into a Terminal window, but creating a Makefile means you can quickly recompile if you make a mistake or you want to go in and tweak the application.

Create a file called "Makefile" with the following code.

all: test

test: Main.cs
	mcs -t:exe -out:SimpleTutorial.exe -pkg:cocoa-sharp *.cs
	rm -rf SimpleTutorial.app
	macpack -m:2 -n:SimpleTutorial -o:. -a:SimpleTutorial.exe -r:Main.nib

Then open a Terminal window, change to the directory where you have saved your files and type the command "make". This will compile your CocoaSharp code with the Mono compiler, and then create a Mac OS X application from the compiled code and the nib file that defines the UI.

The -pkg option on the mcs command makes sure that it's compiled with the cocoasharp package. MacPack is the tool that creates the app bundles for OS X. Make sure you include any nibs/images/icons/etc as a resource by using the -r option of macpack.

Finished

Well, you should now be finished. If all went well you should see an application called SimpleTutorial. Double click on it, and you should see the SimpleTutorial application running.

Click on the button and you should see the text "Form Loaded" change to "Button Pushed".