According to Hoyle...
Looking Forward to Mac OS X 10.5 Leopard, Part III: Objective-C 2.0 Enhancements
[ Part I | Part II | Part III ]
by Jonathan Hoyle
jonhoyle@mac.com
macCompanion
October 2007
http://www.jonhoyle.com
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 (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 History
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
parenthesis. Those 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
developers.
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:
-(MyObjectType *) getSpecialObject:(NSArray *) myArray
{
NSEnumerator *myEnumerator = [myArray objectEnumerator];
MyObjectType *myObject;
while (true)
{
myObject = [myEnumerator nextObject];
if (myObject == nil)
break;
if ([myObject isSpecial])
return myObject;
}
HandleErrorCondition();
return nil;
}
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 simply as:
-(MyObjectType *) getSpecialObject:(NSArray *) myArray
{
for (MyObjectType *myObject in myArray)
if ([myObject isSpecial])
return myObject;
HandleErrorCondition();
return nil;
}
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 the
foreach keyword.
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:
myReturnVal = myObject.foo(parm1, parm2, parm3); // C++
myReturnVal = [myObject foo:parm1, bar2:parm2, bar3:parm3]; // Objective-C
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
equivalent:
z = [x y]; // Objective-C 1.0 syntax
z = x.y; // Objective-C 2.0 syntax
Likewise, the setting of
property data can also be done this way:
[x setY:z]; // Objective-C 1.0 syntax
x.y = z; // Objective-C 2.0 syntax
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:
@interface MyClass
@property(attributes) type name;
// equivalent to:
- (type) name;
- (void) setName:(type)name;
@end
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++, an 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 a
try.
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
throw-ing
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 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).
For more on Objective C 2.0, check out this tutorial.
Coming Up: More development advice for Mac OS X
10.5 Leopard and beyond. See you in
30!
[ Part I | Part II | Part III ]
http://www.maccompanion.com/macc/archives/October2007/Columns/AccordingtoHoyle.htm