TweetFollow Us on Twitter

OpenStep Programming Intro

Volume Number: 13 (1997)
Issue Number: 5
Column Tag: OPENSTEP

What's Inside OPENSTEP... Really?

by Dave Klingler

An Introduction

The next several pages will be an attempt to give you a complete overview of OPENSTEP's development system as it might pertain to Rhapsody. Of course, we can't quite cover everything, but hopefully when you're done reading you'll know a little bit about OPENSTEP's basic parts and why developing under OPENSTEP has brought a happy grin to the faces of so many lucky programmers. OPENSTEP isn't perfect, but it's a well-designed springboard for a Macintosh programming renaissance during the next few years.

The major elements of OPENSTEP are the Foundation Kit, Interface Builder, Display Postscript, and Objective-C. There are some important minor players as well: ProjectBuilder, Header Viewer, Librarian and pswrap. All of these elements are probably unfamiliar to you unless you've used NEXTSTEP or OPENSTEP before, so let's start by taking a quick run through the development process under OPENSTEP to see where the pieces fit. We'll then go back to take a closer look at the major players.

The Development Process

The development cycle under OPENSTEP is fast enough that it tends to leave you wondering what you skipped when you're finished. I'll outline my own development cycle here; you'll probably evolve your own techniques once you start programming under OPENSTEP.

I usually begin by designing classes. This process is similar in any modern language; I figure out what data my program will use and derive a rough list of the major classes involved. Optimizing for speed versus efficiency, or server storage versus local storage, maintainability or even communications bandwidth will influence the design of my class system.

Over a period of about my first two years working with Objective-C I noticed that my techniques for designing new objects changed radically and often. I attribute that to the seemingly subtle, but huge differences between designing for Objective-C and for conventional languages like C or Pascal or even quasi-oop languages like C++. I take heavy advantage of dynamic typing and dynamic binding, which are not available in most languages other than Smalltalk. Java is currently mostly statically typed as well, but JDK 1.1 has reflection, a clear sign that the language is evolving in the right direction.

Bizarrely enough, I've gotten to the point where I write almost all my overview documentation before I write most of the code. I'll write test code to make sure a concept's going to work if it's something radical, but for the most part the code's completely described before it's written. I'm finished when any competent Objective-C programmer could write my app from my docs.

The documentation process is made easier by the fact that every Objective-C class is comprised of an interface file and a class implementation file. The interface file is a fancy header file that contains all the class variables that might be needed by a programmer using the class, plus prototypes for class methods and functions. When I'm designing a new class, of necessity I have to decide how that class will interact with the outside world. Whatever's externally available goes in the interface file and, with a comparatively tiny amount of work, an explanation goes with it into the documentation. Now I've got my interface files and all the documentation someone would need to use any of the classes in my new app.

At this point I'll either hand it off to a group of programmers for them to complete or paste the method and function prototypes from the interface into a new file called the class implementation file and begin filling out the class. This is the file that will actually contain the code for the class, and if you want to sell your classes you can compile this file and sell the result along with the interface file and the documentation. No one gets your source code, but they do get an explanation of all the classes' externally available variables and methods. Their classes can interface with your classes without knowing what's inside them, and that, after all, is what object-oriented programming is all about.

Lots of people in the OPENSTEP world sell classes instead of applications. One of the first classes I bought was BenaTong's Serial class, so that I could save some work writing a telecommunications package.

Because I've got a list of method prototypes to implement, I can just work my way through the file coding each one. When I reach the last one the class will be finished and quite often it "just works" with little or no debugging.

After designing the classes, it's time to pull out ProjectBuilder. ProjectBuilder manages the process of building a new application, module or palette under OPENSTEP. I tell ProjectBuilder to create a new project, create a few icons for the program and data files and drop them into ProjectBuilder's various boxes, drop in the new classes and double-click the "nib" file that ProjectBuilder has created for me. "Nib" stands for NeXT InterfaceBuilder, and that file contains the elements of the interface for the program, arguably most of it. Using Interface Builder might be compared to using a graphical version of ResEdit, but InterfaceBuilder does much more.

Next I design the rest of the program. Keep in mind that most of the elements in the average program other than the ones you've just designed (and they're usually very few) are already running in the OPENSTEP OS. This means that you can use "live" versions of those objects when you design your program's user interface by just grabbing what you want off a palette. You can also put your new classes into their own palette and use them too.

InterfaceBuilder allows you to design a program and "run" it without actually ever compiling it, because the code for any objects you're using other than your own has already been compiled. That code is running or at least available in the operating system as a shared library. When you've finished "drawing" your program the way you want it to work, including the classes you can't see but must be integrated anyway, you select "test interface" from InterfaceBuilder's menu and InterfaceBuilder runs the program for you without classes that it doesn't have yet. It gives you a big Frankenstein-style switch that you can use to shut the program down if your experiment doesn't like to quit. If you don't like the user interface, you can play with it until it's easy to use or does exactly what you wanted. It's far more powerful than an ordinary interface design program because you effectively have a graphical window into the guts of your app.

To release my application in other countries I can design nibs in other languages. OPENSTEP has support for English, French, Spanish, Swedish, German and Japanese. Most of the time it's just a matter of changing the words on the menus. There are localization firms that specialize in taking an English nib file and using it to create other language-specific versions of the program. They'll send back the nib and you can drop it into ProjectBuilder. They'll also translate other messages that reside in your code if it's needed. In most cases your app will "just work" in any language your customer chooses to use.

When I finish with InterfaceBuilder (and I might reverse the process and play with InterfaceBuilder first because it's sometimes more productive) I tell ProjectBuilder to compile the app. I'll select "debug" first if the app is large or I'm trying something fancy. If I'm debugging, ProjectBuilder will build the app with all its nibs and then compile the new classes with debugging extensions. It'll then drop me into gdb (a debugger) with the app loaded, where it's up to me to debug. There are various other debugging tools available under OPENSTEP that allow me to examine the app's messaging, memory usage, optimization, etc. Quite often if I'm really bamboozled I'll tell gdb to show me all the messaging taking place between objects. It's something like watching your children begin to talk.

I haven't yet discussed Postscript wraps or the cool process of trying out your Postscript code in (there's a server running in the os, so why not?) before it goes into your project. ProjectBuilder knows about wraps and various other resources too, so it's an extremely useful tool for managing the process of creating a large application. Let's take a look at wraps and Display Postscript in general.

Display Postscript

Display Postscript (DPS) did not exist when NeXT first got together with Adobe to design a common language for writing to the screen and the printer. The general idea was to achieve true WYSIWYG by using the same code to describe both, and so DPS was born. Steve Jobs waxed poetic about XWindows while describing why NeXT had chosen DPS over X11; he called X "brain damaged". It is true that like many groundbreaking efforts, X became a little outmoded, and DPS is an elegant system. DPS is, however, imperfect in the context of the new age of multimedia, so we'll probably see many additions to DPS over the next few years.

Depending on your program's performance needs, there are various methods available for adding Display Postscript to your programs. Note that most programs use very little DPS, and unless you're designing a drawing application you probably won't have to learn much. That said, playing with Postscript interactively can be somewhat addictive, like fooling with turtle graphics and Logo if you're old enough to remember. You may choose to spend more time with it than is absolutely necessary, and if you do, the principles are the same.

You may or may not know that Postscript is a stack-based client-server page description system. Your program is the client, and the server is effectively either the screen or the printer. In theory it would be nice to write code that worked on both screen and printer; in practice you can't rely on all printers being Level II Postscript-compatible, so you may have to rewrite small sections of your display code for safe printing if you want to use Level II features.

There are three basic methods for using Display Postscript: operator functions, wraps and user paths, in descending order of their execution times. Operator functions are simplest, and you'll use them when you want to make a quick call to the server for a single function. Here's an example of a common combination of commands in Postscript, a "moveto" command followed by a "lineto" command. They create what is known in Postscript as a "path, and they're followed by an instruction to "stroke" the path, or fill it with ink.

10 10 moveto
50 50 lineto

As mentioned, one of the really fun parts of OPENSTEP is getting into Yap (Yet Another Postscript processor) and playing with Postscript interactively. Some time ago I ported BattleZone to NEXTSTEP, and I threw the entire opening screen into Yap to test it. I then moved elements of it around until I was happy with the way the screen looked. It was so much fun it almost made up for the rest of the porting process.

You can include these instructions in your code by using PS operator functions. OPENSTEP has two PS library functions for every PS operator, one for drawing in a default context and one that allows you to specify the context. Here's the equivalent of what's above, using the PS operator functions in psops.h, which draw in a default context:

PSmoveto(10, 10);

Now you've seen the original Postscript and the way you can implement it using single operator functions. As you can see, it is easy to convert any Postscript calls into operator function calls and insert them into your program. The problem with doing that is that each one of these calls is a separate message to the server. If you're calling one function occasionally, you're sending one message to the server occasionally, which is as good as you're going to get. For more than one line of Postscript, however, you'd do better to package your Postscript into a "wrap".

A wrap packages your calls into a C function library that ProjectBuilder can be told to include at compile time. You'd write a text file with the following in it:

/ML {% X1 Y1 X Y
} bind def
defineps multiline(float data[x]; int x; int length) 
  1 1 length ML for

Drop this into ProjectBuilder, which will call a program called "pswrap", to turn the file into a friendly, eminently readable and efficient package that looks like this:

/* ./sym/c_gpr.c generated from c_gpr.psw
  by unix pswrap V1.009 Wed Apr 19 17:50:24 PDT 1989  */
#include <dpsclient/dpsfriends.h>
#include <string.h>
#line 1 "c_gpr.psw"
#line 10 "./sym/c_gpr.c"
void PSWDefs( void ) 
 typedef struct {
  unsigned char tokenType; 
  unsigned char topLevelCount;
  unsigned short nBytes;
  DPSBinObjGeneric obj0;
  DPSBinObjGeneric obj1;
  DPSBinObjGeneric obj2;
  DPSBinObjGeneric obj3;
  DPSBinObjGeneric obj4;
  DPSBinObjGeneric obj5;
  char obj6[2];
  } _dpsQ;
 static const _dpsQ _dpsF = {
  {DPS_LITERAL|DPS_NAME, 0, 2, 48},/* ML */
  {DPS_EXEC|DPS_ARRAY, 0, 2, 32},
  {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME, 14},    /* bind */
  {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME, 51},    /* def */
  {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME,107},    /* moveto */
  {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME, 99},    /* lineto */
  }; /* _dpsQ */
 register DPSContext _dpsCurCtxt = DPSPrivCurrentContext();
 char pad[3];
 DPSBinObjSeqWrite(_dpsCurCtxt,(char *) &_dpsF,54);
 if (0) *pad = 0;/* quiets compiler warnings */
#line 7 "c_gpr.psw"
#line 43 "./sym/c_gpr.c"
void multiline(const float data[], int x, int length)
 typedef struct {

  unsigned char tokenType;
  unsigned char topLevelCount;
  unsigned short nBytes;
  DPSBinObjGeneric obj0;
  DPSBinObjGeneric obj1;
  DPSBinObjGeneric obj2;
  DPSBinObjGeneric obj3;
  DPSBinObjGeneric obj4;
  DPSBinObjGeneric obj5;
  } _dpsQ;
 typedef struct {
  char obj6[2];
  } _dpsQ1;
 static const _dpsQ _dpsStat = {
  {DPS_LITERAL|DPS_ARRAY, 0, 0, 48}, /* param[var]: data */
  {DPS_LITERAL|DPS_INT, 0, 0, 1},
  {DPS_LITERAL|DPS_INT, 0, 0, 1},
  {DPS_LITERAL|DPS_INT, 0, 0, 0},  /* param: length */
  {DPS_EXEC|DPS_NAME, 0, 2, 48}, /* ML */
  {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME, 72},    /* for */
  }; /* _dpsQ */
 static const _dpsQ1 _dpsF1 = {
  }; /* _dpsQ1 */
 _dpsQ _dpsF;  /* local copy */
 register DPSContext _dpsCurCtxt = DPSPrivCurrentContext();
 char pad[3];
 register DPSBinObjRec *_dpsP = (DPSBinObjRec *)&_dpsF.obj0;
 register int _dps_offset = 48;
 _dpsF = _dpsStat; /* assign automatic variable */
 _dpsP[0].length = x;
 _dpsP[3].val.integerVal = length;
 _dpsP[0].val.arrayVal = _dps_offset;
 _dps_offset += x * sizeof(DPSBinObjGeneric);
 _dpsP[4].val.stringVal = _dps_offset;
 _dps_offset += 2;
 _dpsF.nBytes = _dps_offset+4;
 DPSBinObjSeqWrite(_dpsCurCtxt,(char *) &_dpsF,52);
 dps_tFloat, (char *)data, x);
 DPSWriteStringChars(_dpsCurCtxt,(char *) &_dpsF1,2);
 if (0) *pad = 0;  /* quiets compiler warnings */
#line 12 "c_gpr.psw"

As you can see, it's easier to work in Postscript and let ProjectBuilder or pswrap do the work for you. It's also not a good idea to look too often at the files that pswrap generates, because you'll begin losing sleep.

There's a third way to interact with the DPS server, and that's with user paths. A user path is a way of packaging up a bunch of Postscript and translating it beforehand for the server. You can go even further by telling the server to store it in a user dictionary. That way you can make one call to the server, perhaps to supply arguments, and you minimize your program's messaging overhead. The technique is available when you need it, but from experience I can tell you that it's easier to use wraps and then go back and optimize where necessary with user paths. User paths are sometimes not very easy to debug.

For the most part whenever you use Postscript, you'll be drawing in a "View" object, a part of the Application Kit that maintains its own state for Postscript operations. Let's go back for a look at InterfaceBuilder and the Appkit and see why InterfaceBuilder plays such a large part in OPENSTEP programming.

Interface Builder

On the surface InterfaceBuilder looks essentially just like any interface builder. What it's doing underneath is far more rich and, in the end, far more useful to the programmer. InterfaceBuilder allows you to assemble all of the elements of your program and test them, in some cases without even compiling the program. You do this by grabbing objects off a palette and placing them where you want them. You can use almost any object in the Application Kit, which is an extremely rich source of material, or you can also make up palettes of your own objects and drop them into InterfaceBuilder.

A side benefit of using InterfaceBuilder is that much of your program will automatically conform to the OPENSTEP user interface standards. InterfaceBuilder doesn't limit you to creating applications. You can create modules as well, for use in other apps. After you're done bringing in the various elements of your program, InterfaceBuilder allows you to define the relationships these elements will use to work together. When you're finished, you can test your application without compiling it from within InterfaceBuilder. If a program works in InterfaceBuilder, it usually works after it's been compiled. Sometimes you'll even find yourself writing programs that never even run outside of InterfaceBuilder.

There are three major parts of InterfaceBuilder other than the area in the middle of the screen where you assemble your apps. The first is the file window (Figure 1), where all the different parts of your app are kept, including the parts that have no visual interface. As you add pieces to your application you'll see icons for each instance appear in the file window. You can also instantiate your own objects as you write code for them and they will appear here.

Figure 1. The File Window contains all the pieces of an application.

The file window keeps track of sounds, images, and information about the different classes available to you as well. You can use the file window's class browser to browse through the classes for a particular class. The class browser will allow you to parse new classes into InterfaceBuilder for use with the other objects. You can also subclass existing classes in the file window, and InterfaceBuilder will write skeleton code for your new subclass, including any action methods or outlets (pointers to other objects) your subclass might have. You can add these action methods and outlets in the Inspector window. Inspector windows are one of the most important user interface innovations in OPENSTEP, and a number of MacOS and Windows programs have begun using them. Essentially an inspector gathers all the important information about an object in one place. InterfaceBuilder makes fundamental use of inspectors in a most artful manner.

Figure 2. An InterfaceBuilder Attributes inspector window.

Figure 2 shows an InterfaceBuilder Attributes inspector for a fictitious button in a fictitious application. It's what you'd see if you selected the button in the same manner as selecting a line in a drawing program. The Attributes inspector allows you to change the title of the button instance, the icon it displays, the sound it makes, what kind of button it is (momentary push, pushOn/pushOff, etc.), and various other attributes. You can either specify sounds or icons by typing their names into the inspector or you can drop them on to the button and they'll appear here. InterfaceBuilder's Inspector Window carries all the important information about an individual object.

In addition to attributes you'll see other common elements such as details on the object's connections to other objects (messages it might receive or send, and to or from whom), the object's size in various dimensions, or help attachments to an interface element. In short, the Inspector Window contains detail. Last but not least is the Palette Window. It's the most intuitive window to use, because you simply drag objects from the palette to the application window or panel in which they should reside. You can drag Window and Panel objects, too.

Figure 3. InterfaceBuilder's Pallette window.

When you've finished dragging, browsing, parsing, clicking and typing, it's time to finish your application by drawing connections between all the different objects. When you've finished, your objects will be able to send messages to one another, and you can test them by selecting "Test Interface" in the menu. When you're all finished, click "Save" and InterfaceBuilder will archive the objects for you in a nib file. The nib contains most of the information about a program, and as you can see, anything in the nib is machine non-specific. That's why apps written in OPENSTEP are easily delivered across processor architectures. InterfaceBuilder is very cool.

Objective-C, alias Objective-C++

Fear not Objective-C. Yes, it is another programming language. It will, however, give you a competitive advantage in development that you probably don't believe possible right now. It's also easy to learn, and before you mumble to yourself that you've heard that before, let's take a look.

Objective-C was designed by Brad Cox, Smalltalk guru and the author of "Object-Oriented Programming, An Evolutionary Approach", a seminal work in OOP circles. He chose to make Objective-C a mix between Smalltalk and C, attempting to keep the best features of both. Objective-C takes dynamic typing and dynamic binding from Smalltalk. Within a class, however, it preserves the conciseness and efficiency of C.

On the surface, there are basically three differences between Objective-C and C:

1. Objective-C has a type called "id" that functions as a pointer to a generic object.

2. id is the default return type, rather than an int.

3. Objective-C has a messaging syntax for calling a method within an object. It uses embedded arguments, and it looks like

[object method] 

Here's an example of a message to a hypothetical object called graphObject to plot a point at location (x,y,z) with color graphColor:

[graphObject plotXAt:x andYAt:y andZAt:z 

The syntax may seem strange with the embedded arguments thrown in, but it's not all that confusing. The method could be prototyped as

- (void) plotXAt: (float) x 
     andYAt: (float) y 
     andZAt: (float) z 
    withColor: (float) color;

The idea is that the format is more conducive to designing readable code. You can give your methods sentence-like names like the one above. I've been able to return to code I haven't seen for over a year and begin where I left off. I have never found another programming language that allows an ease of overall maintainability that compares to that of Objective-C. Syntax, however, may make Objective-C maintainable, but that isn't what makes it powerful. What makes it powerful is its features, and my favorite features of Objective-C are dynamic typing and binding.

The utility of a generic pointer to an object is that it gives the programmer the ability to point to an object without knowing what it is beforehand. Objective-C has reflection and discovery, so I can point to an unknown object and ask it to describe itself and whether it knows how to do certain things.

By using id to point to the object rather than statically typing it at runtime as an object of class X (you can do that too), I'm telling my program not to worry about what the object is yet. The object will be bound at runtime, and permiting me to choose what object I want during the program's execution instead of being forced to predict it at the link stage. The object I bind with at runtime could be written years after the calling code, and the calling program wouldn't know the difference.

Dynamic binding, dynamic typing and object discovery and reflection allow me to utilize true polymorphism. I might have several different code libraries containing classes that all have the same names but do different things. I might have a method call in a class, for instance, that looks like

[storageObject insertRecord:record];

One application might call for the storage method to be a hashtable. Another application might be best suited with a stack. The same class could be used for both, without any rewriting, because my stack class and hashtable class understand the same methods. All of this flexibility might be hard to manage, except that Objective-C allows me to declare formal protocols for classes to obey. A class declaration in Objective-C looks like


The same class declaration with an instruction to the compiler to make sure that the class follows a formal protocol looks like

 Object < BlowsUpThings, CannotBeStopped >

Protocols are truly powerful because they allow the programmer to easily take advantage of extreme polymorphism. A class can send the same message to classes of entirely different inheritance subtrees, which leads us to inheritance and scope coherency.

Scope coherency is not an issue with Objective-C; it uses a single inheritance model. If it's necessary to inherit methods of a wildly disparate nature that don't fit into a single inheritance model easily (and my experience has been that this case is rare), I can group methods into Categories. Categories aren't only good for that purpose, however; they're an extremely powerful tool with many uses.

Using a category, I can add methods to a class without having its source code. Effectively, I can extend classes that are already running, and all subclasses of those classes will inherit the abilities you added transparently.

I can also group like methods in a very large class into various categories. That ability nets me incremental compilation, better locality of reference, configurability of classes for special needs, and a way to divide up a large class among multiple developers.

With OPENSTEP, NeXT brought many of the best features of C++ into Objective-C, renaming the language Objective-C++. The end result is an extremely powerful marriage, sort of like C++ with a clean syntax and much-improved maintainability.

Some members of the Java team originally worked for NeXT, and Java resembles Objective-C far more closely on a structural level than it does C++. If you've looked into Java, and liked it, you'll love Objective-C.

Foundation Kit

Development under NEXTSTEP has always basically been AppKit + Objective-C + DPS, which somehow magically added up to more than the sum of their parts. Over the years, though, there were many NEXTSTEP developers who argued that NEXTSTEP was somehow impure in a few ways. It lacked garbage collection. It had no string objects. It didn't support Unicode. Many of the problems we discussed were along the lines of the perennial "why should the user throw the disk away to eject it?" discussion in the Mac world.

With OPENSTEP, NeXT had a chance to redo some things in a better fashion. Unfortunately, they were still under time pressure, which meant that some of the changes weren't optimal solutions. Still, OPENSTEP makes some good improvements on an already elegant foundation. NEXTSTEP was the first step; OPENSTEP is the next step.

Foundation Kit brings some final polish to the OPENSTEP development environment. It brings some basic utility classes, like NSArray, NSThread, and NSException. It brings reference counting. It brings Unicode strings. It brings... complexity. It brings slowness and bulk. Such is the price of power and maturity.

Mac developers are already familiar with Unicode. Foundation Kit defines the following encodings supported by NSString classes:

Encoding: Purpose:

NSASCIIStringEncoding for strict 7-bit ASCII encoding within 8-bit chars

NSEUCStringEncoding for Japanese text

NSISOStringEncoding for ISO Latin 1

NSNEXTSTEPStringEncoding for 8-bit ASCII encoding with some extensions

NSNonLossyASCIIStringEncoding (undefined)

NSSymbolStringEncoding (undefined)

NSUnicodeStringEncoding standard Unicode encoding for string objects

NSUTFStringEncoding 8-bit Unicode for transmission by ASCII-based systems

If you produce software that must be localized, you'll have plenty of fun with these. There's an encoding for every purpose.

Support for Unicode is important, but what's arguably an even bigger addition with Foundation Kit is that it brings garbage collection and standardized exception handling.

NeXT's solution to garbage collection is reference counting - possibly not the most elegant solution they could have chosen, but it's robust and it works. Basically the Application object for each application keeps an autorelease pool for storing references to objects. When an object is allocated or copied from another object, it is given a reference count of 1. Every message from another object to retain an object increments the reference count; every message to "autorelease" the object decrements it. When the reference count reaches 0, the autorelease pool releases the object.

To understand a little bit better, imagine that you have an object called spy. The spy object has the ability to concoct fantastic schemes to take over the world.

So if another object, say, the Control object, messages spy with a message to concoct a new scheme:

   [spy concoctScheme];

then spy might do something like

- (void) concoctScheme
   [currentScheme autorelease];
   currentScheme = [ [ Scheme alloc ] init ];

The rule is that if you create an object, you are responsible for releasing it. By sending currentScheme an autorelease message before returning it, spy is declaring that currentScheme does not need to exist beyond the current scope. By the way, the above example also illustrates nesting of messages, which works in a similar way to nesting function calls.

What if the spy had already passed the currentScheme object to its trusted partner, dirtyCounterSpy, and then subsequently sent the autorelease message to currentScheme as above? Eventually the other object might message the old currentScheme, which has probably long since been auto-released, and the dirtyCounterSpy object would crash hard, taking Control and spy and all the other objects in the secret espionage program with it.

The way to solve that would be for dirtyCounterSpy to send the older currentScheme object a retain message. Sending a retain message increments the older currentScheme's reference count in the autorelease pool. That way when the spy object sends an "autorelease" message to currentScheme, the reference count drops only to 1 instead of 0. The dirtyCounterSpy object can now keep the currentScheme object even though the object has been released by the spy object, and, in fact, even if the spy object is destroyed the dirtyCounterSpy object can use "retain" to keep currentScheme.

I hope this dirty lesson in in the affairs of espionage has briefly illustrated reference counting, and perhaps in other, more exciting ways it's illustrated a little of the power of OPENSTEP. There's quite a bit more to Foundation Kit, mostly in the area of abstraction, that is somewhat beyond the scope of this article. You have what you need, however, to grab a copy of Rhapsody and create that killer app.

Apple Inc.
Microsoft Corpora
Google Inc.

MacTech Search:
Community Search:

Software Updates via MacUpdate

Apple Security Update 2014-005 - For OS...
Apple Security Update is recommended for all users and improves the security of Mac OS X. For information on the security content of this update, please visit this website: Read more
EyeTV 3.6.6 - Watch and record TV on you...
EyeTV brings a rich TV experience to your Mac. Watch live TV on your Mac. Pause, rewind, and record whenever you want. EyeTV gives you powerful control over what you watch and how you watch it. Put... Read more
RapidWeaver 6.0 - Create template-based...
RapidWeaver is a next-generation Web design application to help you easily create professional-looking Web sites in minutes. No knowledge of complex code is required, RapidWeaver will take care of... Read more
NTFS 12.0.39 - Provides full read and wr...
Paragon NTFS breaks down the barriers between Windows and OS X. Paragon NTFS effectively solves the communication problems between the Mac system and NTFS, providing full read and write access to... Read more
RestoreMeNot 2.0.3 - Disable window rest...
RestoreMeNot provides a simple way to disable the window restoration for individual applications so that you can fine-tune this behavior to suit your needs. Please note that RestoreMeNot is designed... Read more
Macgo Blu-ray Player - Blu-r...
Macgo Mac Blu-ray Player can bring you the most unforgettable Blu-ray experience on your Mac. Overview Macgo Mac Blu-ray Player can satisfy just about every need you could possibly have in a Blu-ray... Read more
Apple iOS 8.1 - The latest version of Ap...
The latest version of iOS can be downloaded through iTunes. Apple iOS 8 comes with big updates to apps you use every day, like Messages and Photos. A whole new way to share content with your family.... Read more
TechTool Pro 7.0.5 - Hard drive and syst...
TechTool Pro is now 7, and this is the most advanced version of the acclaimed Macintosh troubleshooting utility created in its 20-year history. Micromat has redeveloped TechTool Pro 7 to be fully 64... Read more
PDFKey Pro 4.0.2 - Edit and print passwo...
PDFKey Pro can unlock PDF documents protected for printing and copying when you've forgotten your password. It can now also protect your PDF files with a password to prevent unauthorized access and/... Read more
Yasu 2.9.1 - System maintenance app; per...
Yasu was originally created with System Administrators who service large groups of workstations in mind, Yasu (Yet Another System Utility) was made to do a specific group of maintenance tasks... Read more

Latest Forum Discussions

See All

The Silent Age Episode 2 Review
The Silent Age Episode 2 Review By Jennifer Allen on October 22nd, 2014 Our Rating: :: ROUNDING THINGS OFF NICELYUniversal App - Designed for iPhone and iPad Rounding off a great point and click adventure comes The Silent Age... | Read more »
Craft Your Own Mini-Games with Papercade
Craft Your Own Mini-Games with Papercade Posted by Jessica Fisher on October 22nd, 2014 [ permalink ] iPad Only App - Designed for the iPad Scrapbookers move over, Scrapgaming is the new thing. | Read more »
Reshape Review
Reshape Review By Jennifer Allen on October 22nd, 2014 Our Rating: :: SIMPLE SHAPESUniversal App - Designed for iPhone and iPad Match triangles together to form cubes in this fast-paced and twitchy game.   | Read more »
Miika (Games)
Miika 1.0.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.0 (iTunes) Description: Miika is a beautiful 3D puzzle game based on camera perspectives combined with the use of optical illusions. Miika challenges... | Read more »
Infuse Pro (Photography)
Infuse Pro 3.0 Device: iOS Universal Category: Photography Price: $9.99, Version: 3.0 (iTunes) Description: ** All-new version 3 includes fully licensed and certified DTS® and DTS-HD® audio! ** | Read more »
Swap Heroes (Games)
Swap Heroes 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: **Half price for a limited time only** Swap Heroes is a casual turn-based strategy adventure. Form a group of heroes and guide them... | Read more »
Ghost Blade (Games)
Ghost Blade 1.1 Device: iOS Universal Category: Games Price: $4.99, Version: 1.1 (iTunes) Description: Get the most outstanding 3D Action Game from App Store NOW! For those who dare pursue dreams. Masterpiece of Yu Shi Game ---China... | Read more »
Fiete – A Day on a Farm Review
Fiete – A Day on a Farm Review By Amy Solomon on October 21st, 2014 Our Rating: :: A MEMORABLE EXPERIENCEUniversal App - Designed for iPhone and iPad Fiete – A day on a farm in an interactive app for young children full of... | Read more »
Tilt to Live: Gauntlet’s Revenge is Almo...
Tilt to Live: Gauntlet’s Revenge is Almost Here Posted by Jessica Fisher on October 21st, 2014 [ permalink ] One Man Left has announced the official release date of Tilt to Live: Gauntlet’s Re | Read more »
Starfly Review
Starfly Review By Jennifer Allen on October 21st, 2014 Our Rating: :: CHANGE OF PACEiPad Only App - Designed for the iPad Want a slightly different browsing experience? Starfly is a pretty personalized one but it’s also buggy.   | Read more »

Price Scanner via

AT&T accepting preorders for new iPads fo...
AT&T Wireless is accepting preorders for the new iPad Air 2 and iPad mini 3, cellular models, for $100 off MSRP with a 2-year service agreement: - 16GB iPad Air 2 WiFi + Cellular: $529.99 - 64GB... Read more
Apple offering refurbished Mac Pros for up to...
The Apple Store is offering Apple Certified Refurbished 2013 Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Select MacBook Airs $100 off MSRP, free shipp...
B&H Photo has 2014 a couple of MacBook Airs on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels Desktop and LoJack for... Read more
13-inch 2.5GHz MacBook Pro on sale for $100 o...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $999.99 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
Strong iPhone, Mac And App Store Sales Drive...
Apple on Monday announced financial results for its fiscal 2014 fourth quarter ended September 27, 2014. The Company posted quarterly revenue of $42.1 billion and quarterly net profit of $8.5 billion... Read more
Apple Posts How-To For OS X Recovery
OS X 10.7 Lion and later include OS X Recovery. This feature includes all of the tools you need to reinstall OS X, repair your disk, and even restore from a Time Machine backup. OS X Recovery... Read more
Mac OS X Versions (Builds) Supported By Vario...
Apple Support has posted a handy resource explaining which Mac OS X versions (builds) originally shipped with or are available for your computer via retail discs, downloads, or Software Update. Apple... Read more
Deals on 2011 13-inch MacBook Airs, from $649
Daily Steals has the Mid-2011 13″ 1.7GHz i5 MacBook Air (4GB/128GB) available for $699 with a 90 day warranty. The Mid-2011 13″ 1.7GHz i5 MacBook Air (4GB/128GB SSD) is available for $649 at Other... Read more
2013 15-inch 2.0GHz Retina MacBook Pro availa...
B&H Photo has leftover previous-generation 15″ 2.0GHz Retina MacBook Pros now available for $1599 including free shipping plus NY sales tax only. Their price is $400 off original MSRP. B&H... Read more
Updated iPad Prices
We’ve updated our iPad Air Price Tracker and our iPad mini Price Tracker with the latest information on prices and availability from Apple and other resellers, including the new iPad Air 2 and the... Read more

Jobs Board

Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.