According to Hoyle...
Looking Forward to Mac OS X
10.5 Leopard, Part III: Objective-C 2.0 Enhancements
by Jonathan Hoyle
This month, Apple will be introducing the
sixth major release of Mac OS X: version 10.5 Leopard. With each release, Mac OS X has
succeeded in improving stability, usability and power. Earlier this year,
Microsoft released Vista,
an update to it Windows operating system, with somewhat disappointing sales.
To get an interesting (and very amusing) comparison of Vista and the current Mac OS X 10.4 Tiger, I strongly suggest you visit this YouTube video link (taken from last year's
Worldwide Developer's Conference).
As the video suggests, Vista is an
attempt to copy Mac OS X's past. This month's release of 10.5 Leopard is a big step toward the Mac's future.
In July, we began our look with an
overview of the 2007 Worldwide Developer's Conference. In August, we examined
in earnest the changes coming in Leopard from a user's perspective, and then last month, we reviewed
Xcode 3, Apple's new development tool update for Leopard. You can view these articles here:
This month, we begin concentrating on
specific issues related to Leopard software development. As mentioned in previous columns, Mac OS X 10.5
Leopard is still
prerelease software and is under a Non-Disclosure Agreement. For that reason,
I can relay only on information that Apple has already revealed to the public,
despite Leopard's release being only a couple of weeks away.
Between now and Mac OS X 10.5's release, an excellent resource is
at: Apple's Leopard page.
The 64-bit Challenge
The price of 64-bit development went up
by a lot this year, with Apple announcing that Carbon development is
unsupported beyond 32-bit. Carbon is the C/C++-based programmer's interface
which traces its history back to the original Macintosh from 1984. Until very
recently, the vast majority of commercial Macintosh products were built with
Carbon. The announcement to desupport 64-bit Carbon came as quite a surprise
for many, as Apple's remarks at last year's WWDC was completely the reverse. In
2006, Apple provided a 64-bit Transition Guide for Carbon, detailing a process for developers to
port their Carbon projects for 64-bit compilation. Many companies spent this
past year affecting those changes, just to discover in June that the rug has
been pulled out from under them. Carbon projects slated for 64-bit support have
to be completely rewritten to have any chance of becoming 64-bit.
To take advantage of the 64-bit operating
system, most developers will be switching to the Objective-C based Cocoa API.
However, there are other possibilities. Darwin, Unix and X11 developers will see no impediment moving
to 64-bit with their current code base. Likewise, Java developers will be able to run virtually
unmodified in 64-bit mode on Intel-based Macintoshes (although PowerPC-based
Macs will run Java in 32-bit only, even on the 64-bit G5 processor). Those
developing in frameworks may find themselves in trouble, since most
Mac-supported C++ frameworks are Carbon-based. Trolltech's Qt framework uses Carbon and thus Qt-based apps will not be 64-bit any time soon.
Trolltech announced their decision to change their Mac OS X implementation from
Carbon to Cocoa, but they have no idea how long this is going to take. Those
using the open source wxWidgets framework are in a slightly better position. Although the main Mac OS X branch
of wxWidgets is
Carbon-based, there has been a ongoing initiative for the last several years
for a Cocoa implementation, called wxCocoa. It seems to me that suddenly wxCocoa will begin to receive attention from a
much wider audience. I have seen no official word from other C++ frameworks
like CPLAT or FLTK, but it cannot be good news for them.
Even non-C++ project may be impacted, such as those using the very popular REALbasic development environment,
which is still primarily written in Carbon.
For more information on transitioning to
64-bit development, visit Apple's 64-bit page on Leopard.
Objective-C & Leopard
With Apple's elimination of Carbon from
64-bit discussion, the Objective-C programming language is no longer an option
for the Macintosh software developer. The reason for this is that the Cocoa
API's native language is Objective-C, and to use Cocoa, you must acquire
fluency in this language. Many longtime C/C++ programmers have resisted having
to learn it, since all their needs were satisfied by Carbon in C and C++.
Unfortunately, those days are coming to an end, and Mac developers who wish to
remain relevant will want to learn Objective-C.
"Isn't Java also a supported language
for developing Cocoa applications?" someone is bound to ask. Well no, not any more
unfortunately. In the early days of Cocoa on Mac OS X, Apple recognized that
there was a great deal of resistance in using a relatively obscure programming
language like Objective-C. So to be as receptive as possible, Apple provided
two language accesses for the Cocoa API: Objective-C and Java. The choice of
adding Java was an obvious one, due to its immense popularity amongst
developers. Apple's hope was that Cocoa would become embraced by the huge
hordes of Java developers. This turned out not to be the case, as Java
programmers continued to prefer cross-platform APIs, such as AWT and Swing. C/C++ programmers remained with Carbon,
leaving only academics and old NeXT developers (already familiar with
Objective-C) interested in Cocoa. So Apple has recently announced that the use
of Java for Cocoa development is officially deprecated with Leopard. Objective-C is the only
Apple-supported language for Cocoa development moving forward.
Despite its deprecation, there remains a
small but strong contingent of Cocoa/Java developers who plan to stay with
their technology for as long as it remains viable. If you wish to learn more
about developing Cocoa applications with Java, check out this MacTech article: Writing Cocoa Applications in Java.
Objective-C is not a new language by any means. It was created in
the early 1980's during a time when Object Oriented programming was just
starting to become mature. Although there were already a number of pure O.O.
languages in existence, these were mostly niche languages with a small number
of advocates. The development community yearned for a way to extend the popular
C programming language in such a way as to become object oriented. There were
many object-oriented variants of C which were developed, including THINK C
with Objects used by
many Macintosh developers. These language variants for the most part died away
as C++ became standardized. So powerful and so influential did C++ become,
that the vast majority of newer languages today have adopted the C++ syntax
style of object-dot-method-left parenthesis-ordered argument list-right
learning Java, PHP, Ruby or others will find it very easy to go from one
language to another because of this widespread syntax adoption.
Objective-C was an early variant that did
not adopt this standard syntax. Instead it used the rather unusual Smalltalk
bracket syntax, with an argument list prefixed by tags and colons. It lacked
most of the rich features found in C++ but did have some powerful capabilities
not available in C++, namely reflection and a dynamic runtime model. Despite
these advantages, it remained a niche language, surviving almost exclusively on NeXT computers. When
Apple bought NeXT in December 1996, Objective-C became available for Macintosh
With Mac OS X 10.5 Leopard, Objective-C is seeing its first major
facelift, adding a number of new features to the language to make it on par
with other modern languages. This update is called Objective-C 2.0, and we will be looking at some of it
new features this month.
Automatic Garbage Collection
The most significant of enhancement
coming to Objective-C 2.0 is Garbage Collection: the language runtime process which
automatically deletes allocated memory which is no longer in use. Essentially
all modern languages (post-C++) do this, and adding this capability to
Objective-C 2.0 shows Apple's commitment to its preferred language.
Garbage Collecting in Objective-C 2.0 is
an Opt-In proposition, so you choose to turn it on if you wish:
Although you may have some older
Objective-C projects that you do not wish to take the time to convert, all new
projects should start with this flag turned on by default. It is fully
supported in Cocoa and all public frameworks, as all NSObjects are collectable. It does not, however, rewire or replace C's malloc() function or C++'s new operator, so you must replace these yourself.
If you are converting an old project, you
need to be concerned about older memory management calls, as -retain, -release, -retainCount, -autorelease and -dealloc are each ignored when GC is turned on.
However, the equivalent CoreFoundation functions CFRetain() and CFRelease() remain meaningful, as they are meant to
be available to Carbon/C++ developers as well.
Fast Enumeration (foreach)
Another feature added to Objective-C 2.0
is what Apple calls Fast Enumeration. It is essentially what modern languages call a foreach capability. The best way to explain
it is to see the code for yourself. In this example, we have an Objective-C
method which takes an NSArray of MyObjectType, and iterates through the array looking
for the first one which returns true from a call to isSpecial.
In Objective-C 1.0, such code might look something like this:
*) getSpecialObject: (NSArray *) myArray
NSEnumerator *myEnumerator = [myArray objectEnumerator];
= [myEnumerator nextObject];
if (myObject == nil)
if ([myObject isSpecial])
First, an NSEnumerator has to be created for our loop. With each iteration, a call to nextObject has to be performed to acquire
the next item, a check against nil is
made so as to see if the array is completely traversed, and then finally a call
to isSpecial is made
to see if we have found our object. This was a slow and memory intensive
procedure, primarily because we rely on the NSEnumerator to tell give us the object (or nil when
it is completed). With Objective-C 2.0, this same code could be written more
*) getSpecialObject: (NSArray *) myArray
for (MyObjectType *myObject in myArray)
if ([myObject isSpecial])
Here, all of the enumeration complexity of
the prior code sample is completely subsumed by the for ( in ) syntax. In some other languages, this
same syntax is used except the for keyword is replaced by foreach. With
this, no NSEnumerator is needed, and
the code is more concise and readable.
Finally! The Dot Operator!
One of Objective-C's biggest annoyances
is its ugly syntax. In almost all other C-based languages, square brackets are
used exclusively for array indexing. Finding objects, methods and colons
sprinkled inside standalone brackets strikes the new programmer as dismayingly
bizarre. For example, the same function written in C++ and Objective-C may be
invoked this way:
= myObject.foo(parm1, parm2, parm3); // C++
= [myObject foo:parm1, bar2:parm2, bar3:parm3]; //
I wish I could tell you that with
Objective-C 2.0 the brackets are gone. Unfortunately, I cannot. However, I can
tell you that many of the instances in which they were required can now be
avoided with the use of the standardized Dot Operator. One can now obtain property data from
an Objective-C class this way. For example, the following two lines are now
z = [x
y]; // Objective-C 1.0 syntax
x.y; // Objective-C 2.0
Likewise, the setting of
property data can also be done this way:
setY:z]; // Objective-C 1.0 syntax
z; // Objective-C 2.0
This works with any -name / -setName:accessor pattern. Essentially, anything that
looks like an accessor method can now be dotted. The only limitation is that x must be a known class type.
Unfortunately, the declaration of these properties still remains munged in
Objective-C's peculiar syntax:
@property(attributes) type name;
// equivalent to:
- (type) name;
- (void) setName:(type)name;
Objective-C Adopting the C++ Exception Model
Like C++, the Objective-C has an
exception model built into the language. Unfortunately, its implementation is a
very poor one relative to C++. In C++, exception check is designed to be essentially zero cost. The cost
of entering a try block is not more than entering any new scope. The performance hit is taken
only during a throw,
that is when the exceptional circumstance actually takes place. This is
important since the performance cost of a throw is an order of magnitude greater than
In Objective-C 1.0, the reverse is the
case: the @try call takes an order of magnitude longer than the actual @throw.
Since a typical programmer will enter a try block far more often than throw from it, exception handling becomes an
expensive proposition for the Objective-C developer. Apple has addressed this
matter in Objective-C 2.0. Although backward compatibility prevents Apple from
changing this model for 32-bit applications, 64-bit applications written with
Objective-C 2.0 will use the zero cost C++ exception model. With this, entering
a try block becomes fast and throwing
an exception would be slow.
Another nice feature is the
interoperability of exceptions between Objective-C 2.0 and C++. The C++ catch(...) will catch Objective-C exceptions,
whilst throw; rethrows them. Likewise, Objective-C's
has implemented a new @catch(...) call, which will catch any uncaught exceptions (including C++ exceptions) and @throw; rethrows them.
Despite the different models used between
the 32- and 64-bit runtimes, exception handling remains mostly source
compatible. The main difference being that in 32-bit, the new @catch(...) call is implemented like @catch(id e).
Coming Up: More development advice for Mac OS X
10.5 Leopard and beyond. See you in