|
© 6-8-01 Mike Vannorsdel
Since the roll out of Mac OS X
on March 24th, Mac users were introduced to
the terms Carbon and Cocoa. Many
users know the general idea of what these terms
mean, and many more have no idea at all.
In simple terms, Carbon applications
can run on both Mac OS 9 and Mac OS X. Cocoa
applications can run only on Mac OS X. It would
seem to the average person that producing a
Carbon application would be much more attractive
since your application will will cover both
platforms. But there are specific reasons that
can make either option more attractive to the
developer.
First, what does Carbon really
mean? How does it work? Apple has decided that
now is the time to overhaul the aging Mac OS
that we all love and know. With a complete rebuild
from the bottom up, Mac OS X is now the foundation
to which the next decade or so of the Macintosh
legacy will be built upon. But as with every
change, bad follows with the good. With such
a drastic change in one fail swoop, every application
ever made for the Mac OS would now become incompatible.
Obviously, this would not sit well with any
Mac user, current or future. Nor would this
make upgrading to Mac OS X enticing. This is
where Carbon comes in.
Carbon provides a middle step
in the transition between Mac OS 9 and the new
Mac OS X. Carbon offers a way for developers
to take their existing software titles, and
with relatively little more work, add compatibility
with Mac OS X without giving up their Mac OS
9 support. Carbonizing an application can be
a quick, easy task, or months of work. But it
will always be less than that involved in a
complete rewrite. The difficulty and time involved
in carbonization depends greatly on the size
and nature of the application. Large applications
such as Adobe's Photoshop or Microsoft's Office
suite are guaranteed to be a lot of work simply
because of their sheer code size. For an application
to be carbonized, developers must look through
their code and find APIs that are not Carbon
compatible and replace them with alternate versions
that are. Sometimes there is not a direct replacement
Carbon API in which case the developer will
have to redo most of their implementation to
fit with the closest Carbon alternative.
Another issue Carbon developers
must address is designing their controls to
look good in both Platinum (OS 9) and Aqua (OS
X). Controls such as buttons, text fields, ect,
tend to be larger in Aqua. An application that
was designed around Platinum may look plain
ugly in Aqua as buttons are not wide enough
to display their titles and text fields may
not line up with each other. This was commonly
seen in early Carbon applications, and still
in some today. Developers are also encouraged
to use Mac OS X specific features such as alert
sheets to better fit the application with the
Aqua environment.
Carbon applications function by
linking to CarbonLib, when running in Mac OS
9, or the Carbon Framework, when running in
Mac OS X. Though the Carbon application can
make the same API calls for both platforms,
they're interpreted differently by CarbonLib
and the Carbon Framework where each will execute
the appropriate actions for its native environment.
But here's where it gets tricky.
Not all Carbon applications run in both Mac
OS 9 and Mac OS X. Some will only run in Mac
OS X. These are known as Carbon Mach-O applications.
Examples of these would be the Mac OS X Finder
or Internet Explorer Preview included with Mac
OS X. Carbon Mach-O applications still use the
Carbon Framework rather than Cocoa. Building
a Carbon Mach-O application allows the developer
to better integrate their application with Mac
OS X without having to move to an entirely new
framework and language. Applications that run
in both Mac OS 9 and Mac OS X are known as Carbon
CFM applications.
The tools used to create Carbon
applications vary. Most developers will use
Metrowerks' CodeWarrior with either the PowerPlant
or MacApp framework. Others may use REAL Software's
REALbasic or Apple's Project Builder. Each having
its pros and cons.
Cocoa is Apple's object-oriented
framework used for building Mac OS X applications.
The Cocoa Framework allows developers to use
just about all that Mac OS X offers. Cocoa can
be seen as two parts, the Application Kit and
the Foundation. The Application Kit contains
the classes specific to applications such as
user interface controls and document handling.
The Foundation classes cover lower level functionality
such as file I/O and multithreading.
Cocoa has become the preferred
choice for application development on Mac OS
X. This is due to the immaturity of Carbon and
the gap in functionality between the two. Cocoa's
roots come from NeXTStep, the grandparent of
Mac OS X. This explains why most of the classes
are prefixed with "NS", ie: NSApplication, NSFileHandle,
NSThread. However, quite a lot of the Cocoa
Framework has been updated for Mac OS X's new
technologies.
There is a significant learning
curve involved with using the Cocoa Framework.
Once a developer gets past the initial concepts
and ideas, programming with Cocoa is relatively
easy. For starters, a developer must know or
learn the Objective-C language, a super set
of C. You may also use Java, but this implementation
is not as complete or as elegant as of this
writing. Some programmers coming from a non
object-oriented background such as ANSI C will
also need to learn the concepts involved with
object-oriented programming. Finally, developers
will also need to become familiar with the Cocoa
Framework itself.
The classes in the Cocoa Framework
are easy to understand. Each class has an intuitive
name like NSSavePanel which manages save windows,
NSPopupButton for managing popup buttons, ect.
And each member function also has an intuitive
name such as NSArray's objectAtIndex: or NSString's
writeToFile:atomically:.
Cocoa applications by nature dynamically
control memory usage. When memory is needed,
it's allocated, used, then released when no
longer needed. This way the application only
uses the memory it needs when it needs it. In
contrast, Carbon and Classic applications in
Mac OS 9 and earlier were given a predetermined
amount, which is usually near the application's
maximum usage. This means that memory which
is not currently in use is not available for
other applications that may need it. For an
example of Cocoa's dynamic handling, you would
create an object instance of the class you want
to use:
NSString
* myString;
Here we're making a pointer for
our object.
myString
= [NSString alloc];
Here we're allocating memory space
for the object.
myString
= [myString initWithString:@"Hello World"];
here we're initializing the object
with the string value "Hello World"
And as any programmer familiar
with using malloc knows, we better free the
memory when we're done with our object and before
the pointer to it goes out of scope.
[myString
release];
And here we're deallocating our
object
If you're not familiar with Objective-C,
the syntax will look foreign to you. But this
gives the basic idea behind Cocoa's dynamic
memory nature. Nearly every Cocoa object is
allocated and eventually released on the fly.
Cocoa also adds the concept of auto-release
pools. You can create objects that are owned
by the local auto-release pool. The auto-release
pool will automatically deallocate objects when
they are no longer needed.
NSString
* myString = [NSString stringWithString:@"Hello
World"];
This one line creates an NSString
object, initializes it with "Hello World", and
gives it to the auto-release pool. Once doing
this, you will no longer need to worry about
releasing myString as the auto-release pool
will do it for you.
This just scratches the surface
of Cocoa memory management. It also just scratches
the surface of the many features offered by
Cocoa such as Distributed Objects that allows
sharing objects between threads and tasks.
A notable cravat with Cocoa is
that the class implementations are closed source.
This severely limits subclassing. But not to
fear, delegate messages and notifications come
to the rescue. Normally, if you wanted to execute
a piece of code just before your application
quits, such as saving preferences, you'd subclass
the application class and add your code just
before the application quits. However, in Cocoa
there's no need to subclass because the NSApplication
class offers delegate messages and notifications
where you can do this. You can specify an object
as a delegate of another object. This means
that the delegate will act in place of the child
object. In the case above, you could use NSApplication's
delegate method applicationShouldTerminate:
or the notification NSApplicationWillTerminateNotification.
Using the delegate method, the delegate object
can actually interject and stop the termination.
This is useful if a document has unsaved changes
and you want to ask the user whether to save
or not. On the other hand, you could use the
notification. The object who will receive the
notification must first register with the Notification
Center to receive the NSApplicationWillTerminateNotification.
When the application is going to quit, the object
will be notified and can take the desired action.
Delegate methods and notifications do not eliminate
subclassing, but definitely reduces the need
to do so.
The tools that are available for
building Cocoa applications are provided by
Apple. The two major tools are Project Builder
and Interface Builder. Developers should also
know that documentation is scant for Cocoa as
of this writing. But there are other resources
for help, notably Omni
Group's Mac OS X Dev mailing list and StepWise
which has code examples and advanced discussions.
There are also code examples and other documentation
provided with the Developer CD that ships with
Mac OS X.
Hopefully this will make some
sense to both novice users and developers alike
as to what Carbon and Cocoa really are. There
is too much to cover both of these technologies
fully and obviously more than Apple themselves
can document. To this conclusion I'd like to
address some common misconceptions of both technologies.
First, Carbon is not greatly inferior to Cocoa.
Most problems experienced with Carbon applications
are due to the lack of effort on the developer's
part rather than a short coming of Carbon. Admittedly,
it's hard to have an application perform great
on two different platforms, but with time and
effort it can be done. Next, Cocoa is not always
the first pick for new applications. Programmers
who are familiar with the classic APIs may feel
more at home with Carbon, and because of the
learning curve involved with starting Cocoa,
the application may be completed quicker and
with less work. And finally, Cocoa applications
themselves do not automatically use both processors
on multiprocessor machines. The developer, as
for Carbon applications, must do the multithreading
themselves. In Mac OS X, each application has
at least one thread, including Carbon applications.
Mac OS X can run each thread on one processor
or the other. A single threaded application
has only one thread for Mac OS X to work with.
Thus, Mac OS X can split the total number of
threads evenly among both processors. This means
that one application may be using processor
1 and another application using processor 2.
But a single threaded application cannot run
on both processors simultaneously. Applications
that have been multithreaded by the developer
have more than one thread, where each thread
can run independent of each other on the same
processor or on both processors simultaneously.
Granted, some parts of Cocoa applications may
automatically run in a separate thread such
as the animation of a progress bar, but the
bulk of the application will run in the same
thread unless the developer specifically threaded
it.
In conclusion, the technology
used to build an application shouldn't be held
against it. Simply because an application was
built with Cocoa doesn't mean it will run smooth
and flawlessly. And a Carbon application will
not always be the worst application you own.
Email mikevann@applelust.com
|