TweetFollow Us on Twitter

Hot Chocolate

Volume Number: 16 (2000)
Issue Number: 5
Column Tag: Mac OS X Development

Hot Chocolate!

By John Hörnkvist

An Introduction to Cocoa

Introduction

Mac OS X is Apple's great gamble for the future. It does away with almost two decades worth of heritage, and brings advances such as preemptive multitasking, virtual memory and memory protection to the Macintosh. The transition, however, requires that developers port their applications to one of two new APIs; Carbon or Cocoa. While Carbon is clearly the basic element in Apple's plan for bringing existing Mac OS applications to the new operating system, Cocoa offers great opportunities for developers that bring new applications to the market, and to those that are to rewrite from a clean slate. In this article, I will describe what Cocoa is, and how you can take advantage of it.

Apple has repeatedly pointed out that you can write Cocoa applications in either Objective-C or Java. However, Cocoa itself is an Objective-C system, and you'll probably enjoy more of its benefits if you use Objective-C yourself. Therefore, all code examples in this article will be in Objective-C.

Heritage

Cocoa is the latest name for the object oriented software frameworks and technoligies Apple received in the NeXT takeover. In previous incarnations, the technology has been know as YellowBox, OpenStep and NEXTSTEP - and until now, the largest step by far happened in the transition from NEXTSTEP to OpenStep.

The greatest difference between Cocoa and its predecessor is the replacement of Display Postscript by Quartz. While DPS was a very powerful graphics engine, it was a client server system, and an interpreted language, which combined to make life difficult for the performance oriented developer - it was possible to get excellent performance out of DPS, but it required an intimate understanding of the graphics pipeline[1]. With Quartz, graphics display has been moved to a shared memory model, making graphics programming as convenient as the rest of Cocoa - at the cost of making remote display "a third party opportunity".

Cocoa has also gained many important components since Apple took over, such as the document architecture and scriptability.

Cocoa is the latest name for the object oriented software frameworks and technoligies Apple received in the NeXT takeover. In previous incarnations, the technology has been know as YellowBox, OpenStep and NEXTSTEP - and until now, the largest step by far happened in the transition from NEXTSTEP to OpenStep.

The greatest difference between Cocoa and its predecessor is the replacement of Display Postscript by Quartz. While DPS was a very powerful graphics engine, it was a client server system, and an interpreted language, which combined to make life difficult for the performance oriented developer - it was possible to get excellent performance out of DPS, but it required an intimate understanding of the graphics pipeline[1]. With Quartz, graphics display has been moved to a shared memory model, making graphics programming as convenient as the rest of Cocoa - at the cost of making remote display "a third party opportunity".

Cocoa has also gained many important components since Apple took over, such as the document architecture and scriptability.

The Objective-C Language

Objective-C is the brain child of Brad J. Cox, and the result of his worries about the difference in productivity between the hardware and software industries. In the early eighties, he noticed that software development productivity was on a worrying growth curve, and predicted a software crisis if development methodologies did not change. Dr. Cox attributed the difference between hardware and software industries to the fact that the hardware industry used components, such as integrated circuits, ICs, in their designs, and created new components only when necessary. The software industry, at the time using C or Pascal, lacked the component based approach to development, and Dr. Cox set out to change that.

The result of Cox's work was Objective-C, a dynamic object oriented language in the Smalltalk tradition, but built on C. Objective-C allows you to use "software ICs", using Cox's term, to do component based engineering, and it allows you to create new components all the way down to the "transistor level" since it is built on C. Objective-C allows you to drop back to C, but trying to write the program as much in the "Objective" part as possible is a better approach, much like hardware engineers should avoid implementing their designs at the transistor level - unless there is a compelling reason, such as need for extreme performance, that validates the a level approach.

Objects, Instances, Classes, Methods and Messages

Many of the terms used in the article will already be familiar to most readers. Some would claim that the terms are familiar to all; quoting Dr Cox:

"Betsy is a cow" is just a short form of "Betsy is an instance of class cow."

What may be new to some is the context where these terms are used.

An object is a set of private data and some operations, methods, that can access and operate on that data. It is also an instance of a class.

Data is contained within objects as instance variable. In some language, you can also store data in the classes themselves. There is no support for class variables in Objective-C.

A message is a request sent to an object in order for it to perform a method.

A class is a classification of an object, as well as a concrete entity in Objective-C. You can instruct a class to create an instance of itself, and all objects know what class they belong to. In fact, classes are objects themselves.

Since you can send messages to both instances and classes, it is sometimes useful to make a distinction between instance methods and class methods.

A framework is a dynamically loadable library of classes, categories, protocols, functions, and everything else you'd expect from a linked library, optionally bundled with header files, documentation and other resources.

Syntax

Objective-C extends the C syntax in some simple but very powerful ways. Most important is the overloading of brackets as a shorthand for message sending.

Sending a message

There are two ways of sending messages; a cumbersome way using traditional C syntax, and a simple way using the Objective-C syntax.

objc_msgSend(someObject,@selector(someSelector:),someArgument);
[someObject someSelector:someArgument];

However, the Objective-C syntax is most beneficial in cases where you have many arguments to a method.

The NSString class has a method that lets you compare a string to part of another string, with some options, such as case sensitivity.

result=objc_msgSend(aString,@selector(compare:options:range:),
                    anotherString,NSCaseInsensitiveSearch,
                    NSMakeRange(0,10));

result=[aString compare:anotherString 
                options:NSCaseInsensitiveSearch 
                  range:NSMakeRange(0,10)];

Even in a traditional C syntax, without methods and messages, the code would still read

result=compareWithOptionsAndRange(aString,anotherString, 
                                  NSCaseInsensitiveSearch,
                                  NSMakeRange(0,10));

I expect that once used to the somewhat alien look, most will find the Objective-C syntax very easy to read.

Creating a class

To create a class, you start with writing a header file, which holds the interface declaration, much like with traditional C or C++. The following code sample shows a simple subclass of NSObject:

#import <Foundation/Foundation.h>

@interface KitchenTool:NSObject
{
   NSString* name;
}

+ (KitchenTool*) newKitchenToolWithName:(NSString*)aName 
- (NSString*) name;
@end

The name of the class is KitchenTool, its super class is NSObject, it has an instance variable called name, you create it by calling the class method newKitchenToolWithName: (class methods have a plus sign rather than a minus sign before their declaration) and you can retrieve a tool's name by calling the name method.

You also create an implementation of the object, containing the definition of its methods. An implementation of KitchenTool would look like this:

#import "KitchenTool.h"

@implementation KitchenTool

+ (KitchenTool*) newKitchenToolWithName:(NSString*)aName 
{
  KitchenTool* newKitchenTool=[[KitchenTool alloc] init];
  newKitchenTool->name = [aName copy];
  return newKitchenTool;
}

- (NSString*) name
{
  return name;
}

- (void) dealloc
{
  [name release];
  [super dealloc];
}

@end

Take note of the dealloc method; every class that has objects as instance variables should have a dealloc method which releases instance variables during deallocation. The dealloc method sends a message to super, which means that the implementation of dealloc in NSObject, KitchenTool's super class, also gets called.

You may also note that in the newKitchenToolWithName: method, the class object accesses the object as a structure. This is allowed because the class methods are part of the implementation of the class, but I do not recommmed using this feature except in creators for immutable classes.

The use of an #import directive rather than #include avoids loading the same header file multiple times.

Self and Super

When you send a message to an object, you pass the object a pointer to itself, which is called self. The existance of self lets the object use method passing and send messages to itself. Avoiding direct access to instance variables, except in direct accessor methods, and splitting large methods into many smaller ones increases the power of inheritance, and is highly recommended.

Sometimes, you need to access a super class' definition of a method, even though you've overridden it. To send a message that invokes the implementation in the superclass, you use super instead of self when you send the message.

Dynamic features of Objective-C

The use of message passing instead of function calls in Objective-C has some interesting consequences. Among other things, it allows posing, forwarding, categories and swizzling.

Another effect of dynamic message passing is how overriden methods are handled; if you have a class that implements

- (void) someMethod
{
   [self someMethodWithNumber:5];
}

- (void) someMethodWithNumber:(int)aNumber
{
 // Do something with a number
}

and a subclass that overrides this with

- (void) someMethodWithNumber:(int)aNumber
{
 // Do something different with a number
}

then, when someMethod is called on an instance of the subclass, someMethod will use the subclass's implementation of someMethodWithNumber: rather than the implementation in the class where someMethod was defined.

Posing lets a class take the place of its parent in the object hierarchy. The parent class still exists, so the posing object can still callt super, but instances of the parent class will never be created; instead, instances of the poser will be created. A posing class cannot declare new instance variables.

Forwarding is used as a fault handler; when an object receives a message for a method that it doesn't implement, forwarding gives it a chance to pass the message on to another object, or provide some other error handling.

Categories allow you to override or add methods to an existing class, without having to create a subclass or access the source.

Swizzling lets you change the class of an object at any time. This is a dangerous thing to do, but it can be very useful.

To find out more about Objective-C, I suggest reading Object-Oriented Programming and the Objective-C Language, which is available at

<http://developer.apple.com/techpubs/macosx/ObjectiveC/index.html>. For a detailed view, you can also download the implementation of the Objective-C runtime from the Darwin effort.

Frameworks

There are three major parts of Cocoa; Foundation Kit (Foundation), Application Kit (AppKit) and Enterprise Objects (EOF). Foundation is the lowest layer of the system, classes that can be used whether you're building a program without any user interface, or an application with a graphical user interface. The AppKit is built on top of Foundation, and provides graphical functions, as well as high level objects that simplify the construction of applications. Enterprise Objects is a set of frameworks, some built on Foundation and some on AppKit, that provide astoundingly easy and powerful access to databases.

Foundation Kit

The role of the Foundation Kit is to shield the programmer from the underlying operating system by providing calls for memory allocation and deallocation, file access, shared memory, thread management, task management, inter process communication and so forth. It also provides some basic utility classes, such as strings, arrays and dictionaries.

One of the most common mistakes of fledgling Cocoa programmers is to underestimate the richness and flexibility of the Foundation classes. Take a good look at the Foundation class hierarchy before you start writing any new code! On the other hand, a common mistake of more experienced Cocoa programmers is to overuse the Foundation classes. When you know something about your data that can help you make more efficient use of memory and processor power than what Foundation provides, then you should use that knowledge. But make sure that Foundation's classes don't suffice first.

If, for example, you have data that you need to be indexed by date, you could either put it in an NSDictionary, or, you could make your own specialized class for that data. The specialized class is easy to write, and provides better performance. But, writing it creates means having an additional class to test and debug.

Mutable and Immutable objects

In the Foundation Kit, you will find classes named NSArray and NSMutableArray, NSString and NSMutableString and so forth. An immutable object, such as NSArray and NSString, cannot be changed; its contents are set at the time of creation. A mutable object, on the other hand, can have its contents changed at any time. This difference is very useful, since it allows the developer to make some optimizations. For example, if an object contains an NSArray, it can safely pass that array to another object without risking that the array changes, even though the objects in the array can still change internally. If the object uses an NSMutableArray, it is prudent to return a copy of the array.

One should also consider the possibility of mutability when an object is returned from a method. Even if the interface specifies that a method returns an immutable object, the receiver should not rely on the immutability of it; since the mutable class is often a subclass of the immutable class, the compiler will accept an NSMutableArray instead of an NSArray, for example. This also affects thread safety of the classes. While immutable objects are generally safe to use in a multi threaded application, mutable objects need special care. An example of an unsafe implementation is show in listing 1. Further discussion on multithreading in Cocoa is outside the scope of this article, and in fact, Apple has not yet made public what classes will be thread safe in Mac OS X, although it should be safe to assume that classes that are thread safe in earlier version of the framework will remain safe.


Listing 1: Unsafe use of collection objects

- (void)unsafeMethod
{
  NSMutableArray* someArray = [someObject lotsOfObjects];
  int count = [someArray count];
  int i;

  for (i=0;i<count;i++)
    {
     [[someArray objectAtIndex:i] doSomething];
    }

}

- (void)unsafeMethod
{
  NSArray* someArray = [someObject lotsOfObjects];
	// ** Unsafe; the array may be mutable
  int count = [someArray count];
  int i;

  for (i=0;i<count;i++)
    {
     [[someArray objectAtIndex:i] doSomething];
    }

}

Enumerators

Enumerators are objects that represent iteration over a collection of objects, such as an array or a dictionary. Enumerators provide a consistent interface to several kinds of collections, and using them gives code that is easier to read and to change. It also protects you from worrying about changes in the collection you are iterating over; you entrust that to the enumerator.


Listing 2: Iterating over a collection with an enumerator.

- (void)saferMethod
{
  NSEnumerator* enumerator = [[someObject lotsOfObjects] objectEnumerator];
  id theObject=nil;

  while (theObject=[enumerator nextObject])
    [theObject doSomething];
}

The drawback of enumerators is a slight performance cost, and sometimes delayed destruction of objects.

Class clusters

Class clusters are used extensively in the Foundation Kit. Their role is to give a common interface to a set of anonymous classes. There is a class called NSArray in Foundation, but no NSArray objects are created when a program runs. Instead, when you try to allocate an NSArray, you're given an instance of one of NSArray's subclasses. Other class clusters include NSDate and NSString. For each class cluster, there is a minimal set of methods that a subclass has to implement in order to work as a member of the cluster.

When an object is the root of a class cluster, you can't easily subclass it to add functionality. While this may seem limiting at first glance, it is very easy to work around. Instead of writing a subclass, you can write a category on the cluster's root class which extends its behavior, or you can use composition to create a class that combines the capabilities of several classes.

If for example, you wish to create an object that is both an array and a dictionary, you should not do it by creating a subclass of NSArray and implementing dictionary methods on that. Instead, create a new class that composes the functionality of an array and a dictionary.

In fact composition is a very powerful technique, and by using it wisely you'll find that your programs become both smaller and more flexible. Composition is described in detail later in this article.

Object ownership

An important part of Foundation is memory management. Cocoa uses a system known as manual reference counting. When the reference count of an object reaches zero, it is deallocated.

Listing 3 shows how an object can handle retain and release. Note that when an object is allocated, all its instance variables are set to nil. Since Objective-C disregards message passing to nil, it is safe to send messages to uninitialized objects.


Listing 3: An example of retain/release in an object

@interface MyDateKeeper:NSObject
{ 
  NSDate* theDate;
}
- (void) setDate:(NSDate*)someDate;
- (NSDate*) date;
@end

@implementation MyDateKeeper

- (NSDate*) date
{
  return theDate;
}

- (void) setDate:(NSDate*)someDate
{
  NSDate* tmpDate=theDate;
  theDate = [someDate retain];
  [tmpDate release];
}

- (void) dealloc
{
  [theDate release];
  [super dealloc];
}

@end

The rules of retain and release are relatively simple, but nonetheless, it is an area where programmers tend to err. For example, the unsafe method in listing 4 shows a common mistake among unexperienced Cocoa programmers; it is easy to forget that while the conventions for object ownership state that unless you get an object by calling alloc/init or copy, you don't have to release it, it is not guaranteed that the object will stay alive unless you retain it. Learn the rules by heart, because retain/release bugs are among the most difficult to track down.


Listing 4: Safe and unsafe usage of retain and release. The final version using autorelease avoids a memory leak if an exception is raised before release. This safety comes at a performance and memory cost.

- (void) unsafe
{
  NSTimeInterval secondsPerDay = 24 * 60 * 60;
  NSDate* keptDate = [dateKeeper date];
  NSDate *tomorrow = 
					[NSDate dateWithTimeIntervalSinceNow:secondsPerDay];
  if ([keptDate compare:tommorrow] == NSOrderedAscending)  
    {
      NSDate* newDate=0;
      [dateKeeper setDate:tomorrow]; 
        // keptDate may be dealloced 
      newDate=[keptDate laterDate:[NSDate date]]; 
        // and the program may crash
      [self doSomething:newDate];     
   }
}

- (void) safe
{
  NSTimeInterval secondsPerDay = 24 * 60 * 60;
  NSDate* keptDate = [[dateKeeper date] retain];
  NSDate *tomorrow = 
					[NSDate dateWithTimeIntervalSinceNow:secondsPerDay];
  if ([keptDate compare:tommorrow] == NSOrderedAscending)  
    {
      NSDate* newDate=0;
      [dateKeeper setDate:tomorrow]; 
      newDate=[keptDate laterDate:[NSDate date]]; 
      [self doSomething:newDate];     
    }
  [keptDate release];
}

- (void) reallySafe
{
  NSTimeInterval secondsPerDay = 24 * 60 * 60;
  NSDate* keptDate = [[[dateKeeper date] retain] autorelease];
  NSDate *tomorrow = 
					[NSDate dateWithTimeIntervalSinceNow:secondsPerDay];
  if ([keptDate compare:tommorrow] == NSOrderedAscending)  
    {
      NSDate* newDate=0;
      [dateKeeper setDate:tomorrow]; 
      newDate=[keptDate laterDate:[NSDate date]]; 
      [self doSomething:newDate];     
    }
}

Distributed Objects

A highly useful part of Foundation is Distributed Objects. Distributed Objects gives objects in different tasks and threads a convenient way of communication.

The most important parts of Distributed Objects are NSConnection, which encapsulates the communication channel, and NSDistantObject, which acts as a stand in, or a proxy, for an object that lives on the other side of a connection, forwarding messages and handling returned values. A connection can be named, which makes it available to other applications on the systen, or anonymous, which makes it useful for private channels, such as between threads in an application. Communication with distibuted objects is thread safe. Distributed Objects also works over networks, but the semantics for this have changed because of the kernel change in Mac OS X, and it is not yet clear how named object services will work.

Creating and connecting to a connection is very easy, as you can see from listing 5.


Listing 5: Vending an object, and connecting to an object using Distributed Objects

- (void) connect
{
  NSDistantObject* serverObject=
   [NSConnection rootProxyForConnectionWithRegisteredName:@"MyServer" host:@"*"];
}

- (NSConnection*) createConnectionName:(NSString*)name
{
  NSConnection* newConnection=[[NSConnection alloc] init];
  if ([newConnection registerName:@"name"])
    {
      [newConnection setRootObject:self];
    }
  else
    {
      [newConnection release];
      newConnection=nil;
    }
  return newConnection;
}

Extensions to the Foundation

The OmniGroup has a set of highly useful foundation level frameworks that facilitates networking, among other things. You'll find more information about the frameworks and the license at <http://www.omnigroup.com>.

MPWFoundation from Marcel Weiher of Metaobject GmbH is particularly interesting; it offers some useful extensions for higher order programming. For example, the code in listing 2 can be reduced to:

- (void)coolerMethod
{
   [[[someObject lotsOfObjects] do] doSomething];
}

MPWFoundation is not only useful, it's source code is suggested reading for any Cocoa developer. It and an XML parser are available at <http://www.metaobject.com/downloads/Objective-C/Objective-XML-0.1.s.tar.gz>. Both frameworks are mentionware; you have to give credit if you use them.

The MiscKit (<http://www.misckit.com>), a community project managed by Don Yacktman, includes MiscFoundation, which extends the Foundation framework. The MiscKit was a useful resource on NEXTSTEP, but has remained in early beta state on OpenStep/Cocoa for several years. The MiscKit is governed by the MiscKit license.

Sen:te has created OCUnit, and Objective-C version of the Kent Beck's Smalltalk testing framework. OCUnit is highly recommended for developers that value integrated testing support. You can find OCUnit at <http://www.sente.ch/software/ocunit>.

A framework called ConcreteProtocol, that exploits the Objective-C runtime to give a kind of multiple inheritance based on protocols, and a kit for software licensing, LicensingKit can be downloaded from ToastedMarshmallow.com at <http://www.toastedmarshmallow.com>. The LicensingKit is mentionware, and the ConcreteProtocol framework is mentionware for freeware developers, and commercial for commercial developers.

There is also a commercial framework for software licensing called the Licenser Kit from Stone Design (<http://www.stone.com>) and Caffeine software.

Application Kit

The AppKit is the part of Cocoa that is responsible for the graphical user interface. Founded on the dynamic aspect of Objective-C, the kit greatly simplifies the task of creating a user interface. In the AppKit you'll find support for drawing, document based applications, a large collection of useful interface components. The Application kit contains over 100 classes and protocols, which makes it impossible to describe it in its entirety here. Instead some of the more interesting classes will be described.

NSView and NSCell

Whenever there is drawing, there is an NSView. Every window contains at least one view. A view can have a number of subviews, each which can have subviews in its turn.

Views are also where user interaction takes place. A mouse click in a window that isn't directly handled by the window itself will get sent to the highest level view in the window at the point of the click, as a mouseDown: message.

NSTextView is a very useful class for displaying text. It has support for fonts and pictures, as well a fair amount of layout support. While it may not suffice for a word processor, it is usually more than enough for text entry in other applications.

An NSCell can be regarded as a lightweight view class, but in fact it is an object that you draw in a view. Unlike a view, a cell does not have a coordinate system of its own, or any knowledge of its position. The cell is just a representation of some data that can be drawn. The cells have a number of advantages over views; it is faster to draw many cells in a single view than to draw many views, cells need less memory and they can more readily be reused. The drawback is that it is more difficult to set up drawing of a cell. Since the cell doesn't know where to draw itself, or in what coordinate system, you have to set everything up yourself.

One useful cell class is NSImageCell, which composites an image to draw itself.

Mostly, cells are used with existing classes with composition. For example, NSMatrix displays a set of NSCells in a matrix, and NSTableView displays a set of cells as a table. Using your own cell classes with these is trivial.

NSImage and NSImageRep

NSImage and NSImageRep provide a powerful system for compositing and drawing. Before Quartz, one of the image representations was NSEPSImageRep, which allowed you to draw EPS (Encapsulated Postscript) into a view. With Quartz, one may expect an NSPDFImageRep instead. Ine essence, all you need to do to add support for a new image format in Cocoa is to create the proper subclass of NSImageRep; the display system in NSImage is responsible for selecting the proper representation for each image.

The NSCustomImageRep class is interesting, because instead of knowing how to draw itself, it calls a delegate object which does the drawing. By using this class, you can easily make images draw just about any data, and by combining this with NSImageCell, you can get custom drawing in any object that supports cells.

NSImage is a container for image representations. To increase performance, NSImage will cache a representation, so the actual drawing code is only executed the first time the image is composited. However, an NSImage will use a cache only if it fits the resolution and colorspace of the view where it is drawn. This ensures that printed graphics get the highest resolution possible.

NSBezierPath and NSAffineTransform

NSBezierPath is the class for advanced drawing in Cocoa. The advantages of using NSBezierPath instead of discrete drawing commands are that you can create the NSBezierPath once and then draw it over and over, which cleans up your code, and that you can apply transforms to a bezier path before drawing it. While you can apply a transform to the view where the graphic is drawn to achieve the same effect with discrete commands, this is more costly if the graphics needs to be redrawn, since the calculations involved in the transformation have to be done each time the graphic is drawn. With NSBezierPath, the transformation is applied only once, since it affects the drawing commands in the bezier path rather than the canvas.

NSAffineTransform is the transform class of Cocoa. The fact that the transform is affine means that lines that are parallel before the transform are parallel after the transform also. Thus, it does not attempt to do three dimensional transforms such as perspective. However, this is a limitation of Quartz, not of Cocoa; you can create your own transform classes and apply them to NSBezierPaths.

Extensions to the AppKit

The Omni Group has some application level frameworks, some of which are very rich.

The GraphicKit, a structured graphics framework, is available for beta testing at <http://www.toastedmarshmallow.com>.

Finally, the MiscKit's application framework includes several useful components.

Enterprise Objects Framework

Enterprise Objects is a set of frameworks for database access and display of database data. EOF insulates from the particulars of databases; the same program can be used with any database for which you have a database adapter. Thus, a developer can write software that is essentially database independent. EOF uses the Entity-Association (also known as Entity-Relation) model of databases, which makes database modeling very convenient, but maps this onto a relational database model, allowing the use of relational database servers, such as Oracle and Sybase. Since EOF maps to a relational model, you can build applications for existing databases without having to convert the old data to a new format.

Enterprise Objects can be used in server programs, as well as in applications. Whenever you need persistent storage of large amounts of data, EOF is an excellent candidate.

Cocoa Programming Techniques

In Cocoa, you'll find that you can increase your productivity significantly by not programming; with procedural APIs, you'll spend 20% of your time searching libraries, and 80% typing and debugging code. In Cocoa, you spend 20% of your time programming and debugging, 30% searching the frameworks, and 50% enjoying your newly found spare time.

However, sometimes you really must write some new code, and for those occassions, I'd like to point to a number of programming techniques that are highly efficient in Objective-C and Cocoa. Some of these methods should be well known to programmers skilled in C++, but Objective-C has a dynamic dimension which C++ lacks, which affects the choice of design patterns.

Inheritance

Inheritance is the abused workhorse of object oriented programming. If you look at the Cocoa APIs, you'll find that inheritance plays a significant role in the design of the AppKit, but is used sparingly in Foundation. This is done because inheritance creates dependencies between objects, breaking the encapsulation. When inheritance is used, changes to a class may break its subclasses. Thus, use inheritance when the kits point you to that method; NSView is an example of this. Don't use it where it is clear that Apple wants to hide the details, as with the class clusters.

Posing

Posing is useful when you need to refine the behavior of an object, and cannot use a category. It is a rather crude method, and in my opinion should only be resorted to for debugging, and when no other method suffices.

Categories

Categories allow you to add methods to an existing class without subclassing. The advantage of this is that it allows modularity of design - different parts of an object's functionality can be kept in different files and frameworks - and that extensions to a class becomes ubiquitous. Every instance of the class will have the new methods, as will every instance of its sub classes.

Categories override existing methods - unless the developer takes pains to avoid it. This has the advantage that you can replace malfunctioning methods in existing classes without having access to the source. It is also a danger, because you can accidentally override a method - a problem which is accentuated by the lack of name spaces in Objective-C.

Protocols

Protocols define interfaces without specifying an implementation. This allows the compiler and runtime to do type checking based on the interface rather than on the class hierarchy. Protocols are useful when there is functionality that can be implemented in many completely independent ways, and in some cases where multiple inheritance would otherwise be needed.

Whenever an object uses a delegate, it is wise to have a protocol that defines what delegates must be able to do. This allows the compiler to warn the developer if the wrong object is used as a delegate, and it allows the developer to insert runtime checks of protocol conformance.

Protocols are also very useful with Distributed Objects, since you can use protocols to limit the capabilities that an object advertises over a connection, and also to do validity checking on the sending side rather than on the receiving side, which decreases communications and increases performance.

Composition, forwarding and delegates

Composition means combining the capabilities of many classes into one by creating an object that contains several other objects and delegates parts of its responsibility to them. Composition can be used as a replacement for multiple inheritance, but is far more general than that. The great advantage of composition over inheritance is that it can provide shorter and more general code. A simple example is glyphs; instead of creating a subclass for each possible glyph, you create a general glyph class, and use composition to get the attributes you want. I.e. you don't create a TimesRomanGlyph, TimesRomanBoldGlyph, HelveticaGlyph and so forth, but have a character glyph class on which you composite font, color and any other attributes. To generalize further, you may want to create an GlyphAttribute class or protocol, such that Font conforms to the GlyphAttribute protocol, or GlyphFont is a subclass of GlyphAttribute. By doing this carefully, a CharacterGlyph simply becomes a character and a list of attributes. The CharacterGlyph itself has no need to know the particulars of the attributes, since they provide a common interface.

Some advocates of composition claims that it should replace inheritance completely, since it avoids problems such as fragile base classes, and is more flexible. The drawback of composition is that it creates an additional layer of indirection, which decreases performance.

To facilitate composition, NSObject provides a method called forwardInvocation:. When you send an object a message that it doesn't implement, instead of causing an error, forwardInvocation: will be called, giving you a chance to pass the message on to another object.

Delegates are used in a special form of composition. An object hands over a part of its functionality to a delegate object, allowing customization without subclassing. A text object may let the delegate inspect the incoming text and do completion or spell checking on it, for example. An object can also let its delegate observe and decide over certain behaviours. As an example of this pattern, NSWindow uses a delegate with which it confirms that it is OK to perform certain actions, such as closing.

Observers and Notifications

An observer is an object that tracks changes to other objects. Since an object is not allowed to look at the internals of other objects, this must be implemented by having the observed object inform its observer of changes through notifications. However, this would mean that the observed object would have to be aware of all observers, creating unnecessary interdependence between object designs. To avoid this, an notification center acts as a broadcasting station for notifications. The use of a notification center means that the notifier no longer has to be aware of its observers. This is highly useful, because it decouples the observed object from the observer, allowing many different observers to monitor an object without any changes to the object itself. Encapsulation is maintained, since it is the object that decides when to send notifications, although it has no control over who will receive it.

The Foundation Kit provides a notification broadcasting facility, NSNotificationCenter, to which you can send notification objects, NSNotification instances. When a notification center receives a notification, it inspects it, and send it to all objects that have registered as observers for this kind of notification.

Many classes in the Application kit utilize notifications. For example, an NSWindow will send notifications when its status changes, such as when it is moved, sent to another screen, becomes the main window, and so forth. By observing such changes, other parts of the user interface can properly reflect the status of windows.

The difference between delegates and observers is that a delegate is much closer to the observed object; the object knows about its delegate and actively delegates responsibility to it.

Singletons

Singletons are classes that only have one instance. When you try to allocate more objects of such a class, you get the same object back. This is useful when you allocate an immutable object with the same data repeatedly. For example, in a word processor where you represent each glyph with an object, you're likely to have a lot of instances of the letter 'e' in your default font. Then, instead having one copy of the 'e' glyph for each time it appears in the text, you have multiple references to the same glyph instance, saving an immense amount of memory. Of course, this means that the glyph cannot have a notion of position, but that is probably a good design choice in a word processor anyway.

The Model View Controller paradigm

The Model View Controller, or MVC, paradigm has been in the toolbox of object oriented programmers for over two decades. The central idea of this paradigm is breaking an application, or subsystem into three parts; the model, which represents the data in your application, the view, which is the visualization of that data, and the controller, which manages the other objects, such as by taking user input on the view and translating that to changes in the model.

The MVC paradigm is a high level design pattern, and you may have many classes in each category in an application.

The great advantage of the MVC paradigm is that it separates the data storage code from the display code and the user interface code, making it relatively easy to create a new user interface for an application. Thus, you can create a web based interface for a database application, while sharing the database code with the Aqua interface, for example.


The Cocoa application kit is extrememly suitable for MVC programming, and the document support in Cocoa follows the MVC paradigm. There is an Apple article called "Application Design for Scripting, Documents, and Undo" that explains this concept further. [<http://developer.apple.com/techpubs/macosx/>]

Development tools

Cocoa development is centered around ProjectBuilder, an application which lets you edit and create files, which manages the compiler, and interacts with InterfaceBuilder to let you create user interfaces for your applications. InterfaceBuilder is a fully object oriented user interface design application built on a palette model of components.

Another part of the tool suite is EOModeler, which lets you create Enterprise Objects data base models. You can drag database objects from EOModeler to InterfaceBuilder to quickly create user interfaces for database applications.

ProjectBuilder

ProjectBuilder has always been a relatively simple integrated development environment, and a fair amount of complaints about it has been heard from Macintosh developers that are converting to OPENSTEP. NeXT was a small company and didn't have the resources to perfect every part of the developer environment, but with Apple's significantly greater resources, the rough edges of ProjectBuilder should be polished off before the release of Mac OS X.


Figure 1. A fresh framework project in ProjectBuilder

ProjectBuilder utilizes adapted versions common tools to do much of its job; it uses the Gnu C Compiler (gcc), gnumake and the Gnu debugger (gdb). The use of these tools is hidden to a varying degree; gcc and gnumake live quietly in the background, while the user has to interact directly with the debugger to use the full power of gdb.

Despite its faults ProjectBuilder does an acceptable job even in its pre-X state, and its indexing and formatting functions for Objective-C code are quite good. Extensions to ProjectBuilder provide word completion and other features.

InterfaceBuilder

When I first tried to learn NextStep development back in 1994, InterfaceBuilder was by far the greatest hurdle I ran into; the conceptual step from traditional procedural user interface development to InterfaceBuilder's pure object model was simply too great. It took over a month before I figured out that you couldn't understand how NextStep programs work by looking at the code, you had to look at the connections between objects, and that those connection lived in the interface binaries.

In InterfaceBuilder, you create user interfaces by dragging and dropping components from palettes, by instantiating control and model objects, by creating connections between objects and by the setting objects' instance variables. Figure 2 shows how the target of a button titled "Done" is connected to the licenseDone: method of the object called "AppDelegate". (Naming the objects is not necessary, InterfaceBuilder will create a default name based on the object's class, but it is a convenient way of documenting the interface.)


Figure 2. Connecting a button to an action in Interface Builder

Unlike many GUI builders, InterfaceBuilder does not create code, instead it creates an interface description, in Mac OS X this will be saved as an XML file. The interface description is a complete picture of the state of the objects in the user interface - sometimes refered to as freeze dried objects.

Component palettes

With a small effort, any user interface object can be turned into a palette, but for most applications, the palettes that come with InterfaceBuilder are sufficient.

Once you have an object as a component of a palette, you don't need to create a new palette for subclasses; by using the "custom class" inspector, you can tell interface builder to use any subclass of the palette component. This is property is set for each instance, rather that for each class, which means that you're can use a separate custom class for each button in your interface, should the need arise. (If it does arise, you're likely to be better off by using composition than by subclassing, but InterfaceBuilder doesn't force you to follow that approach.)

Apple is likely to refine InterfaceBuilder before the final release, but the palette organization from OPENSTEP 4.2 gives at least an idea of what we can expect.

The menu palette gives you easy access to the default Cocoa menu structure. By simply dragging the document menu onto the menu bar, you get the exact menu structure that Apple's user interface guidelines recommend. Custom menus can be created with the "Item" and "Submenu" components.


Figure 3. The Menu Palette

The view palette contains most of the day to day interface components; sliders, buttons, text fields, radio buttons, color well and drop down menu, as well as a CustomView component which is used to represent any subclass of NSView. By using this component, you avoid having to create a new palette for each new view class.


The View Palette

The window palette provides a panel component and a window component. Panels are intended to be used for support dutities, while windows are the primary user interface component.


The Window Palette

The DataView palette gives access to the text view, with support for plaintext, RTF and HTML, as well as to the image view and to the date and number formatters, which can be used with display cells to provide proper formatting of dates and numbers, with localization support.


The DataView Palette

Creating object instances

For objects that don't exist in palettes, you can create instances from InterfaceBuilder's class browser. This is intended for control and model objects, object that support the user interface, but don't provide direct user interaction.


InterfaceBuilder's class browser

EOModeler

Since Enterprise Objects uses the Entity-Association model of databases, EOModeler is used to create an enterprise model from an existing relational database model, or to create an enterprise model, from which EOModeler creates the relational database model.


EOModeller's diagram view of a database model

Enterprise Objects is also the base for WebObjects, and a full exploration of its possibilities would fill many volumes.

Further Reading

There are currently very few books on Cocoa. A decent substitute is "NeXTSTEP Programming, Step One: Object Oriented Applications" by Simson Garfinkel and Michael Mahoney, which is based on NeXTSTEP rather than Cocoa, but will give an introduction to the concepts of dynamic object oriented programming, and to many of the ideas in Cocoa.

  • Apple provides some good documentation in their developer section, under
    <http://developer.apple.com/techpubs/macosx/macosx.html>. Particularly interesting are "Object-Oriented Programming and the Objective-C Language", "OPENSTEP Development Tools & Techniques" and the articles under "Programming Topics". The references for Foundation and AppKit are also suggested reading.
  • The Objective-C runtime system is part of the Darwin project at <http://publicsource.apple.com>, and is a great help when you need to work with the lowest levels of Objective-C, extending the language itself.
    GNUstep, a free implementation of the OpenStep specification is under progress at <http://www.gnustep.org>. The sources should be helpful to anyone wanting to understand the internals of Cocoa.
  • StepWise (<http://www.stepwise.com>) has an article library with many interesting articles on NEXTSTEP, OPENSTEP and Cocoa programming.

John Hörnkvist is a master student at Chalmers University of Technology in Göteborg, Sweden. He has created a unique academic niche by working on MSc degrees in.both "Computer Science and Engineering" and "Industrial Engineering and Management of Technology". Outside his studies, John has been doing NeXTStep and OPENStep development since 1994, both as an independent developer and as a consultant. His work includes Magnacharta, an application for technical analysis of stock trends, and the Graphickit, a framework for structured graphics. John is also the founder of toastedmarshmallow.com and can be reached as john@toastedmarshmallow.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Whitethorn Games combines two completely...
If you have ever gone fishing then you know that it is a lesson in patience, sitting around waiting for a bite that may never come. Well, that's because you have been doing it wrong, since as Whitehorn Games now demonstrates in new release Skate... | Read more »
Call of Duty Warzone is a Waiting Simula...
It's always fun when a splashy multiplayer game comes to mobile because they are few and far between, so I was excited to see the notification about Call of Duty: Warzone Mobile (finally) launching last week and wanted to try it out. As someone who... | Read more »
Albion Online introduces some massive ne...
Sandbox Interactive has announced an upcoming update to its flagship MMORPG Albion Online, containing massive updates to its existing guild Vs guild systems. Someone clearly rewatched the Helms Deep battle in Lord of the Rings and spent the next... | Read more »
Chucklefish announces launch date of the...
Chucklefish, the indie London-based team we probably all know from developing Terraria or their stint publishing Stardew Valley, has revealed the mobile release date for roguelike deck-builder Wildfrost. Developed by Gaziter and Deadpan Games, the... | Read more »
Netmarble opens pre-registration for act...
It has been close to three years since Netmarble announced they would be adapting the smash series Solo Leveling into a video game, and at last, they have announced the opening of pre-orders for Solo Leveling: Arise. [Read more] | Read more »
PUBG Mobile celebrates sixth anniversary...
For the past six years, PUBG Mobile has been one of the most popular shooters you can play in the palm of your hand, and Krafton is celebrating this milestone and many years of ups by teaming up with hit music man JVKE to create a special song for... | Read more »
ASTRA: Knights of Veda refuse to pump th...
In perhaps the most recent example of being incredibly eager, ASTRA: Knights of Veda has dropped its second collaboration with South Korean boyband Seventeen, named so as it consists of exactly thirteen members and a video collaboration with Lee... | Read more »
Collect all your cats and caterpillars a...
If you are growing tired of trying to build a town with your phone by using it as a tiny, ineffectual shover then fear no longer, as Independent Arts Software has announced the upcoming release of Construction Simulator 4, from the critically... | Read more »
Backbone complete its lineup of 2nd Gene...
With all the ports of big AAA games that have been coming to mobile, it is becoming more convenient than ever to own a good controller, and to help with this Backbone has announced the completion of their 2nd generation product lineup with their... | Read more »
Zenless Zone Zero opens entries for its...
miHoYo, aka HoYoverse, has become such a big name in mobile gaming that it's hard to believe that arguably their flagship title, Genshin Impact, is only three and a half years old. Now, they continue the road to the next title in their world, with... | Read more »

Price Scanner via MacPrices.net

B&H has Apple’s 13-inch M2 MacBook Airs o...
B&H Photo has 13″ MacBook Airs with M2 CPUs and 256GB of storage in stock and on sale for up to $150 off Apple’s new MSRP, starting at only $849. Free 1-2 day delivery is available to most US... Read more
M2 Mac minis on sale for $100-$200 off MSRP,...
B&H Photo has Apple’s M2-powered Mac minis back in stock and on sale today for $100-$200 off MSRP. Free 1-2 day shipping is available for most US addresses: – Mac mini M2/256GB SSD: $499, save $... Read more
Mac Studios with M2 Max and M2 Ultra CPUs on...
B&H Photo has standard-configuration Mac Studios with Apple’s M2 Max & Ultra CPUs in stock today and on Easter sale for $200 off MSRP. Their prices are the lowest available for these models... Read more
Deal Alert! B&H Photo has Apple’s 14-inch...
B&H Photo has new Gray and Black 14″ M3, M3 Pro, and M3 Max MacBook Pros on sale for $200-$300 off MSRP, starting at only $1399. B&H offers free 1-2 day delivery to most US addresses: – 14″ 8... Read more
Department Of Justice Sets Sights On Apple In...
NEWS – The ball has finally dropped on the big Apple. The ball (metaphorically speaking) — an antitrust lawsuit filed in the U.S. on March 21 by the Department of Justice (DOJ) — came down following... Read more
New 13-inch M3 MacBook Air on sale for $999,...
Amazon has Apple’s new 13″ M3 MacBook Air on sale for $100 off MSRP for the first time, now just $999 shipped. Shipping is free: – 13″ MacBook Air (8GB RAM/256GB SSD/Space Gray): $999 $100 off MSRP... Read more
Amazon has Apple’s 9th-generation WiFi iPads...
Amazon has Apple’s 9th generation 10.2″ WiFi iPads on sale for $80-$100 off MSRP, starting only $249. Their prices are the lowest available for new iPads anywhere: – 10″ 64GB WiFi iPad (Space Gray or... Read more
Discounted 14-inch M3 MacBook Pros with 16GB...
Apple retailer Expercom has 14″ MacBook Pros with M3 CPUs and 16GB of standard memory discounted by up to $120 off Apple’s MSRP: – 14″ M3 MacBook Pro (16GB RAM/256GB SSD): $1691.06 $108 off MSRP – 14... Read more
Clearance 15-inch M2 MacBook Airs on sale for...
B&H Photo has Apple’s 15″ MacBook Airs with M2 CPUs (8GB RAM/256GB SSD) in stock today and on clearance sale for $999 in all four colors. Free 1-2 delivery is available to most US addresses.... Read more
Clearance 13-inch M1 MacBook Airs drop to onl...
B&H has Apple’s base 13″ M1 MacBook Air (Space Gray, Silver, & Gold) in stock and on clearance sale today for $300 off MSRP, only $699. Free 1-2 day shipping is available to most addresses in... Read more

Jobs Board

Medical Assistant - Surgical Oncology- *Apple...
Medical Assistant - Surgical Oncology- Apple Hill Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Business Analyst | *Apple* Pay - Banco Popu...
Business Analyst | Apple PayApply now " Apply now + Apply Now + Start applying with LinkedIn Start + Please wait Date:Mar 19, 2024 Location: San Juan-Cupey, PR Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.