As we saw in Chapter 3, Interface Builder is a tremendously powerful program. But IB also hides a lot of the nuts and bolts of how Cocoa applications work, and a knowledge of those nuts and bolts will serve you well as you learn Cocoa programming. In this chapter, we will create a simple Cocoa application in Objective-C without using IB. In the process, we’ll learn the fundamentals of the Objective-C programming language, the Cocoa class hierarchy, and memory management under Cocoa.
In this chapter, we’ll discuss a small application
called Tiny.m
(the
.m
extension means
that the file contains Objective-C code). This program will bring up
a window and will draw a dodecagon (12-sided polygon) with a fancy
pattern in it (see Figure 4-1).
Before discussing the application in detail, we’ll
show you the complete Objective-C source code for
Tiny.m
— Example 4-1.
We’re showing you this now because the best way to
learn a new language is to read a program that’s
written in that language. As you’ll see, much of the
code in Tiny.m
that relates to on-screen objects
will not be necessary when we combine Objective-C with IB.
Tip
Throughout this book, we’ve elected to include comments in the programming examples, even though we are also explaining the code within the book’s text. We do this because it is good programming style to include comments in the code. We hope you’ll get used to using comments in the code that you write.
Example 4-1. Tiny.m
/* Tiny.m * A tiny Cocoa application that creates a window * and then displays graphics in it. * IB is not used to create this application. */ #import <Cocoa/Cocoa.h> // include the Cocoa Frameworks /************************************************************ ** A DemoView instance object of this class draws the image. @interface DemoView : NSView // interface of DemoView class { // (subclass of NSView class) } - (void)drawRect:(NSRect)rect; // instance method interface @end @implementation DemoView // implementation of DemoView class #define X(t) (sin(t)+1) * width * 0.5 // macro for X(t) #define Y(t) (cos(t)+1) * height * 0.5 // macro for Y(t) - (void)drawRect:(NSRect)rect // instance method implementation { double f,g; double const pi = 2 * acos(0.0); int n = 12; // number of sides of the polygon // get the size of the application's window and view objects float width = [self bounds].size.width; float height = [self bounds].size.height; [[NSColor whiteColor] set]; // set the drawing color to white NSRectFill([self bounds]); // fill the view with white // the following statements trace two polygons with n sides // and connect all of the vertices with lines [[NSColor blackColor] set]; // set the drawing color to black for (f=0; f<2*pi; f+=2*pi/n) { // draw the fancy pattern for (g=0; g<2*pi; g+=2*pi/n) { NSPoint p1 = NSMakePoint(X(f),Y(f)); NSPoint p2 = NSMakePoint(X(g),Y(g)); [NSBezierPath strokeLineFromPoint:p1 toPoint:p2]; } } } // end of drawRect: override method /* windowWillClose: is a delegate method that gets invoked when * the on-screen window is about to close (user clicked close box). * In this case, we force the entire application to terminate. */ -(void)windowWillClose:(NSNotification *)notification { [NSApp terminate:self]; } @end // end of DemoView implementation /* * setup( ) performs the functions that would normally be performed by * loading a nib file. */ void setup( ) { NSWindow *myWindow; // typed pointer to NSWindow object NSView *myView; // typed pointer to NSView object NSRect graphicsRect; // contains an origin, width, height // initialize the rectangle variable graphicsRect = NSMakeRect(100.0, 350.0, 400.0, 400.0); myWindow = [ [NSWindow alloc] // create the window initWithContentRect: graphicsRect styleMask:NSTitledWindowMask |NSClosableWindowMask |NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO ]; [myWindow setTitle:@"Tiny Application Window"]; // create amd initialize the DemoView instance myView = [[[DemoView alloc] initWithFrame:graphicsRect] autorelease]; [myWindow setContentView:myView ]; // set window's view [myWindow setDelegate:myView ]; // set window's delegate [myWindow makeKeyAndOrderFront: nil]; // display window } int main( ) { // create the autorelease pool NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // create the application object NSApp = [NSApplication sharedApplication]; // set up the window and drawing mechanism setup( ); // run the main event loop [NSApp run]; // we get here when the window is closed [NSApp release]; // release the app [pool release]; // release the pool return(EXIT_SUCCESS); }
Before we analyze the program, we suggest that you type it in and
save it in a file called Tiny.m
.
Tip
We strongly recommend that you type the examples within this book by hand, rather than downloading them from the Web. You will learn more about Cocoa programming by actually typing in the examples — and then finding your typos — than you will by merely reading them.
You can use any of the text editors that come with Mac OS X:
Project
Builder, TextEdit, GNU
Emacs,
vi
,
or ed
. If you’re just starting
out with Unix, you’ll probably want to use PB or
TextEdit, because they work like most other Cocoa programs and have
several nice features for writing code. TextEdit is the basis of the
editor that’s built into PB. It is extended in PB
with some powerful features for browsing a program’s
source code and interfacing directly with
gdb
, the GNU
debugger we discussed in Chapter 2.
After you’ve typed the source code in the file
Tiny.m
, open a Terminal window and change to the
directory where the file resides. Compile Tiny.m
and then (if there are no errors inadvertently introduced by typing
mistakes) run the executable Tiny
with the
commands shown here in bold type:
%cc -Wall -o Tiny Tiny.m -framework Cocoa
%./Tiny
Tiny is now running — look for its window.
The components of this compiler call command are described in Table 4-1.
Table 4-1. Compiler call command components
What you typed |
What it means |
---|---|
|
Invokes the C compiler. (In Cocoa, the C, Objective-C, and C++
compilers are all invoked with this same command, although the C++
compiler is usually invoked with the
|
|
Makes the compiler list all warnings. |
|
Places the result of the compilation in the |
|
Compiles the program in the |
|
Instructs the linker to use the Cocoa “framework.” |
If the program compiles without errors (and there should be no errors, not even any warnings), you can run it as specified above, by typing “./Tiny” and hitting Return.
You should see the window displayed earlier, in Figure 4-1.
Warning
This demo program lacks many fundamental elements of a standard Cocoa program, and therefore it does not interact properly with the Mac OS X environment. In particular, this program does not display a menu, it does not bring its window to the front of the window stack when it starts up, and it does not appear in the Dock. A side effect of these characteristics is that you may find it difficult to find the Tiny window. If this happens to you, try hiding your running applications until the Tiny window appears.
You can close the Tiny application by clicking the red close button at the top-left corner of its window or by typing Control-C in the Terminal window.
Before we explain how Tiny works, let’s take a detour and look at some basics of the Objective-C programming language. This discussion is not meant to be exhaustive, but rather a foundation on which we can build throughout the rest of the book.
Get Building Cocoa Applications: A Step by Step Guide now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.