Programming Mac OS X with Cocoa for Beginners 2nd Edition/Learning From Hello World

From Wikibooks, open books for an open world
Jump to: navigation, search

Next Page: First Cocoa Program - Hello World | Next Page: First Cocoa Application - Hello World

In the previous page of this wikibook, we created a Mac app called "HelloWorld". Notice that the menus work and that the window works. Try out the HelloWorld app and see what works. On this page of this wikibook, we're going to analyze how HelloWorld works. We're going to analyze the code and the resources that XCode created for us automatically when we created the Mac OS X Cocoa App.

Understanding the HelloWorld Code[edit]

First, we're going to look at the entry-point of the app. The entry point in C programs and in Objective-C programs is the method called main(). See the following code from main.m and the discussion below. Also look in your HelloWorld project, you should have a file called main.m also and the code should be similar if not identical.

main.m

#import <Cocoa/Cocoa.h>
 
int main(int argc, char *argv[])
{
    return NSApplicationMain(argc, (const char **)argv);
}
  1. Notice the #import directive. This is used to import the file Cocoa.h from the Cocoa framework. This opens up all of Cocoa to be used here in the main.m
  2. Next, you'll see the declaration of the main() method. This is all just standard C, the parameters argc and argv specify the command-line parameters which we won't worry about because we're developing GUI applications that aren't launched from the command-line. You could always get these command-line parameters from Cocoa but we won't go into that in this wikibook.
  3. Next, you'll see a call to a function from Cocoa called "NSApplicationMain()" This function initializes the Cocoa framework, passing the command-line arguments to Cocoa, and gives Cocoa control.
  4. When the call to NSApplicationMain() completes, it returns an int which is the status code of the application and this int is returned as the result of the main() method. This status code will be returned to the program that launched this app (usually this will be the Finder).

So that's it for main.m

Next, we'll take a look at the files: AppDelegate.h and AppDelegate.m. You'll have these two files in your HelloWorld project too and you'll want to follow along there:

AppDelegate.h

#import <Cocoa/Cocoa.h>
 
@interface AppDelegate : NSObject <NSApplicationDelegate>
 
@property (assign) NSWindow *window;
 
@end
  1. As in main.m, notice the #import that imports the headers for the entire Cocoa framework, allowing us to use anything in Cocoa.
  2. Next, notice the "@interface". The at symbol @ is the Objective-C escape character which means that what follows isn't regular C, but is an Objective-C extension to C. "interface" really mean that this is the interface for a class declaration.
  3. "AppDelegate" is the name of the class being defined. Notice that "AppDelegate" doesn't start with an "NS" so it isn't part of Cocoa, it's a class declaration that the XCode template made for us.
  4. Then, there is a colon : The colon means that the class name that follows is the parent class for the class being defined.
  5. Following the colon is the identifier "NSObject". NSObject is the base class from which all other classes in Cocoa and from which our own Classes will inherit from.
  6. NSObject is the base class for all objects in Cocoa.
  7. Then there is "NSApplicationDelegate" surrounded by angled brackets <> Because it's within angled brackets, Objective-C knows that "NSApplicationDelegate" is a protocol. This protocol being specified means that AppDelegate can be treated like an NSApplicationDelegate because it implements the necessary methods. For readers familiar with Java, in Java these are called "interfaces". Note that a protocol isn't a class. A protocol merely specifies methods to be implemented. So here, Cocoa's application object will be able to send messages (i.e. call methods) of AppDelegate and Cocoa's application object will know that AppDelegate can handle what it needs to do to help the application object because AppDelegate implements the methods specified by NSApplicationDelegate.
  8. Next, notice "@property (assign) NSWindow *window;" @property here means that "window" is an instance variable of AppDelegate that we're automatically going to generate accessors and mutators for. These methods will be called "window" to access a window and "setWindow:" to set a window, Within the parentheses, we see the word "assign". This means that when this property is set with the mutator, that we're not going to do a copy of the parameter to the mutator, and we're going to do the default for memory management. NSWindow * means that the object referenced by the instance variable called "window" is going to be a pointer to an NSWindow. Remember that all object references in Objective-C are pointers to objects.
  9. Last of all, in this header file, there is the "@end" part. This indicates the end of the @interface part, so this is the end of the class declaration.

AppDelegate.m

#import "AppDelegate.h"
 
@implementation AppDelegate
 
@synthesize window;
 
- (void)dealloc
{
    [super dealloc];
}
 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
}
 
@end
  1. Notice the #import directive here. We're in the implementation file, AppDelegate.m. It needs to import the corresponding class declaration. C and C++ programmers will be used to having a .h file and importing it into the implementation file. Using XCode and Cocoa, for every class, you will generally have two files, a .h file and a .m file. Notice that we only need to import "AppDelegate.h" AppDelegate.h will in turn import Cocoa.h so here, we could have used anything in Cocoa.h in this .m file.
  2. Next, notice the "@synthesize window" command. This coordinates with the corresponding "@interface" command to automatically create an accessor and a mutator. Using @property and @synthesize is especially nice when a class has a lot of instance variables that need accessors and mutators because they are written for you automatically.
  3. Next, is the definition of a method called "dealloc". "dealloc" is used to deallocate an object. dealloc is inherited from NSObject and all of your objects will inherit this method. Notice the syntax of this method's declaration. The dash - means that this method is an instance method -- as opposed to a class method. Being an instance method means that for this method to be called, this method has to be called on an instance that is on an object. For class methods, instead of a dash, there would be a plus sign + indicating that the method can be called on a class. We'll cover class methods later on in this wikibook.
  4. Notice that this default implementation of the dealloc method for this class is just to call the inherited dealloc method using the keyword "super". So, in fact, this dealloc method doesn't really do anything. XCode put it in for us as a reminder that if we allocate anything in our AppDelegate object that we need to deallocate it too.
  5. About memory management sometimes dealloc and other memory management methods (such as retain, release, autorelease) aren't needed any more. You have the option for what's called Automatic Reference Counting (ARC) or garbage collection which are two different alternatives to simplify memory management. The trouble with manual memory management is that if you don't deallocate things that you need to, you can run out of memory. This is called a "memory leak". The opposite problem is that if you deallocate memory and you still need it and the program tries to use it after it's deallocated, the program can behave unpredictably with bugs that are hard to find and/or the program could crash.

Understanding Resources[edit]

It's important to understand that the resources, the menus and the window, contained within the file named HelloWorld.xib does not contain Objective-C code. Let's call these "resource files" "nib files". The nib file is a data file. that is "freeze dried" and can be "thawed out" at runtime and Cocoa can create the specified objects for you without there being any addition code generated. The code that "thaws out" the resources in these nib files is already built into Cocoa.

In XCode find the file "MainMenu.xib".

If you found the file called MainMenu.xib, you can skip this paragraph. With the HelloWorld project open, on the left-hand side of the screen, there should be a list of the files and groups (the group icons look like folder). Find the file, "MainMenu.xib" and click on it just once. If you can't see a list of files and groups, first choose from the "View" menu, then choose "Navigators" then if visible, choose "Show Project Navigator". If "Hide Project Navigator" is displayed instead of "Show Project Navigator", then the project navigator is already being shown.

Now that you've found the file, "MainMenu.xib", click on it just once and the nib editor should be displayed in the center of your XCode window.

In the center panel of your window a nib editor will be opened allowing you to view and edit your main menus along with your main window.

Understanding How Code and Resources Work Together[edit]

Next Page: First Cocoa Program - Hello World | Next Page: First Cocoa Application - Hello World