Objective-C 2.0 Overview

Objective-C 2.0 is a major enhancement to the language that powers the Cocoa programming environment. Designed as a small and powerful set of extensions to ANSI C to support object-oriented message passing, Objective-C is an extremely dynamic and flexible language. It allows you to work at a high level and quickly build sophisticated applications, yet preserves the ability to access the lowest level system libraries and write performance critical code in the most efficient manner possible. Objective-C, combined with the mature and powerful Cocoa frameworks, enables small group of engineers to create great applications.

Fully modernized for Mac OS X Leopard and the 64-bit Cocoa frameworks, Objective-C 2.0 features runtime performance improvements, provides property accessors and fast iteration constructs to its syntax, and adds a throughly modern high-performance garbage collection system implemented to take full advantage of the latest multi-core systems. These new features take Objective-C to the forefront of modern object-oriented languages and allows you to write better applications more quickly and with fewer bugs. These benefits aren't just theoretical: Xcode 3 takes full advantage of all of the new features of Objective-C 2.0. At the same time, the Objective-C 2.0 runtime remains fully compatible with Objective-C 1.0 which means that your existing applications run on Leopard without a hitch.

This article, part of the Leopard Technology Series for Developers, introduces you to the new features of Objective-C 2.0 and its runtime. First, let's look at garbage collection.

Garbage Collection

The introduction of automatic memory management is the most significant change to the Objective-C 2.0 runtime. As in most C-based languages, previous versions of Objective-C required programmers to allocate and release memory manually. To assist in this process, Objective-C provided a reference-counting memory management system using the retain and release keywords. This simplified matters but still required programmers to exercise care to ensure proper memory management.

Replacing the Objective-C 1.0 retain/release based reference counting system, the new, tuned, high-performance garbage collector works hand-in-hand with the strengths of Objective-C and all of the Cocoa libraries that ship with Mac OS X as well as Core Foundation. This brings Objective-C the same ease of memory management that programmers using other modern languages, such as Java, have enjoyed. And, to support all existing Objective-C 1.0 applications, the garbage collector is implemented as an opt-in system. If you have an existing application that you want to run with manual memory management, you don't have to do a thing.

Going one step further, the Objective-C 2.0 garbage collector is implemented as a conservative collector. This gives developers full access to the power of the C language, as well as preserves Objective-C's ability to integrate with C++ code and libraries. This means that Objective-C can directly access any library on the system, from the high level Core Animation and QuickTime frameworks to the lowest-level file system calls. Of course, when working with C and C++, you'll need to continue to manage memory for that code manually using malloc and free. The result, however, is that you can use the most efficient and powerful tool for any programming task. You can create the bulk of your application using Objective-C, letting the garbage collector manage memory and then, just where it's needed, use C or C++ code to perform specialized operations.

Activating the Garbage Collector

To enable garbage collection in your application, all you need to do is enable the Objective-C Garbage Collection build setting. There are three possible values for this setting, as shown in the following figure. For new standalone applications, the Required setting is recommended. This instructs the compiler to use the -fobjc-gc-only flag and will cause Cocoa to automatically initiate garbage collection at suitable points in your application's event cycle. The Supported value sets the -fobjc-gc flag and indicates that your code contains the traditional retain/release logic and can be loaded into any application. This setting is most useful for plugins and libraries that must support both garbage collected and non-garbage collected environments.

image

Once you enable garbage collection for your application, the memory management for all Cocoa and Core Foundation objects is handled by the Objective-C 2.0 runtime. With garbage collection enabled, the older reference count memory management methods of retain, release, and autorelease have no effect. When called, they are short-circuited by the Objective-C runtime. In addition, the dealloc method of garbage objects is no longer called when an object is destroyed. This is because the primary function of the dealloc method is to update reference counts to instance variable objects is no longer needed. It is important to note, however, that the Core Foundation CFRetain and CFRelease methods do still have an effect on Core Foundation objects.

In principle, when the collector runs a full collection, it creates a set of all the valid objects starting with all of the known root objects in your application, including the NSApplication shared instance and other stack-allocated and global variables. The collector then recursively follows normal object references, also known as strong references, from these objects to other objects to form the complete set of valid objects. Once completed, all objects that are not part of this set are considered garbage and are removed from memory. It is important to note that the garbage collector doesn't follow weak references. Sometimes you want to reference an object, but don't want to be responsible for keeping it alive if no other object is interested in it. For this case, you can use a weak reference and, if no other objects have a strong reference to that object, it will be disposed of when the garbage collector runs.

While the garbage collector relieves you from having to manage memory yourself, it does not mean that you can ignore the way that your application uses memory. In particular, you should still ensure that the memory footprint of your application is as small as possible. The easiest way to do this is to ensure that you are only keeping references to objects that you want to keep alive and that you make sure that you are not unintentionally collecting references to otherwise unwanted objects in collections. In general, however, using the new garbage collector will significantly reduce the amount of code that you have to write and maintain and eliminates most typical memory-related problems, such as retain cycles.

Collecting with a Light Touch

When the collector is active and looking for memory to reclaim, it runs on a separate thread from your application. This allows it to do its job without noticeably impacting your application's performance, only blocking threads in your application for as short a time as possible. As well, the collector thread is run at a lower priority than the other threads in your application and may be terminated in the presence of new user events. This further ensures that your application remain responsive at all times to user input.

Another way the new garbage collector reduces its runtime impact is that it uses a generational collection algorithm. This means that the collector leverages the fact that most objects in an object-oriented application are fairly short-lived by nature. As well, these objects are the ones that are most likely to be located in the system's caches. By dividing allocated memory into "generations." the garbage collector can prioritize its attention on the newest generations and recover significant amounts of memory quickly and easily. Less frequently, the collector will run a full collection against the entire object graph of the application to collect long-lived objects that are no longer being used.

Declared Properties

Another important new feature in Objective-C 2.0 is support for declared properties. In object-oriented programming, properties refer to data encapsulated by an object that is accessed through methods instead of being directly accessed through instance variables. Using properties allows you to change the implementation of an object at a later time without affecting the implementation of other objects that use a property.

To better support and encourage the use of properties, Objective-C 2.0 introduces a new declared property syntax to let you add properties to your classes with a minimum of code. Instead of providing lots of repetitive and error-prone boilerplate code, you can now use a concise set of declarations that convey your intention. The compiler then uses these declarations to automatically generate accessor methods as needed to satisfy your class's interface. For example, to add a simple property to a class, you could use the following syntax in the class header:

@interface Person : NSObject {
    NSString *location;
}
@property NSString *location;
@end

This code indicates that the Person class has a property named location that can be read and set. To finish the implementation of the property, add the following code in the class implementation:

@implementation Person
@synthesize location;
@end 

This code instructs the compiler to generate, or synthesize, the accessor methods. The compiler will generate the accessor methods using well-tested, fast algorithms that are ready for multi-core and multi-threaded environments, including locking variables in setter methods. Not only does using properties reduce the amount of code that you have to write, it replaces that code with the best possible accessors for today's modern multi-core systems. Later, if you need to provide an alternative implementation for a property accessor, you can simply add the appropriate code to your class.

Accessing Properties

To use the property of an object in your code, you can use a new dot syntax in Objective-C 2.0 which follows the same pattern as used to access a structure element. For example, to set the location of the Person class above, you can use the following code:

Person *bill = [[Person alloc] init];
bill.location = @"Home"

Then, to access the property, you can use the following line of code:

NSLog(@"Bill's location: %@", bill.location);

The new dot syntax in Objective-C 2.0 is syntactic message to the compiler which is translated at compile time into the invocation of accessor methods. For example, the code above is equivalent to the following method invocations:

Person *bill = [[Person alloc] init];
[bill setLocation:@"Home"];
NSLog(@"Bill's location: %@", [bill location]);

You can use either style of accessor method in your code and maintain the ability to change the implementation of your properties later.

Property Declaration Attributes

By default, when you declare a property, the compiler generates code that treats the property as a read/write property. It also uses simple assignment in the setter. If you need your properties to have a different behavior, there are a set of optional property declaration attributes that you can use. For example, to specify that a copy of an object should be used for assignment, you can declare the property as follows:

@property(copy) NSString *location;

To specify that a property is read-only and that a set accessor method shouldn't be created, you can use the following:

@property(readonly) int age;

There are other property declaration attributes that allow you to specify the names of the get and set accessor methods for a property; indicate if a property accessor method should be non-atomic; and more.

Fast Enumeration

The final major new feature in Objective-C 2.0 is fast enumeration, an Objective-C syntax addition that lets you operate across all the members of a collection simply and easily. Using fast enumeration results in clearer and easier to understand code. For example, if you wanted to iterate over an array of strings, you could use the following code:

NSArray *array = 
    [NSArray arrayWithObjects:@"1", @"2", @"3", nil];

for (NSString *string in array) {
    NSLog(@"string is %@", string);
}

Using fast enumeration is considerably more efficient than using an NSEnumerator object directly. It provides a much more concise syntax. And, best of all, it provides for safe enumeration. If a collection is modified during enumeration, an exception is raised. Since mutation of a collection is forbidden during enumeration, multiple enuermations can be performed on multiple threads concurrently.

Fast enumeration works with any collection that implements the NSFastEnumeration protocol. All of the Cocoa collection classes, including NSArray, NSDictionary, and NSSet, as well as NSEnumerator, implement this protocol. You also add fast enumeration to your own collections by supporting the NSFastEnumeration protocol, which consists of a single method.

Conclusion

As you can see, Objective-C 2.0 brings significant advances to Objective-C. Using garbage collection, the new property syntax, and fast enumeration allows you to write powerful Cocoa applications more quickly with less code. It allows you to better concentrate on writing the code that makes your application unique instead of tedious boilerplate that is repetitive and error-prone. If you're writing new applications for Leopard, you should make full use of the new features in Objective-C 2.0 to write modern Cocoa applications. On the other hand, if you still need to support older versions of Mac OS X, you can code as you always have using Objective-C 1.0 features and your application will run unchanged on Leopard.

Get Started with Leopard

The next generation of the world's most advanced operating system is now available. Tap into the innovative technologies of Mac OS X Leopard and design your products with new and compelling features. With an ADC Premier or Select Membership, you have a range of developer resources from Apple engineers and experts, including ADC on iTunes, Coding Headstarts, the ADC Compatibility Labs and more. Learn how ADC Memberships provide you Apple expertise. From code to market.

Updated: 2007-11-06

 
 
 

Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2009 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice