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.


Community Search:
MacTech Search:

Software Updates via MacUpdate

TextSoap 8.4.1 - Automate tedious text d...
TextSoap can automatically remove unwanted characters, fix up messed up carriage returns, and do pretty much anything else that we can think of to text. Save time and effort. Be more productive. Stop... Read more
TextSoap 8.4.1 - Automate tedious text d...
TextSoap can automatically remove unwanted characters, fix up messed up carriage returns, and do pretty much anything else that we can think of to text. Save time and effort. Be more productive. Stop... Read more
Backblaze - Online backup servi...
Backblaze is an online backup service designed from the ground-up for the Mac. With unlimited storage available for $5 per month, as well as a free 15-day trial, peace of mind is within reach with... Read more
Numi 3.15 - Menu-bar calculator supports...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
EtreCheck 3.3.3 - For troubleshooting yo...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
BusyContacts 1.1.8 - Fast, efficient con...
BusyContacts is a contact manager for OS X that makes creating, finding, and managing contacts faster and more efficient. It brings to contact management the same power, flexibility, and sharing... Read more
TunnelBear 3.0.14 - Subscription-based p...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
Apple Final Cut Pro X 10.3.4 - Professio...
Apple Final Cut Pro X is a professional video editing solution.Completely redesigned from the ground up, Final Cut Pro adds extraordinary speed, quality, and flexibility to every part of the post-... Read more
Hopper Disassembler 4.2.1- - Binary disa...
Hopper Disassembler is a binary disassembler, decompiler, and debugger for 32-bit and 64-bit executables. It will let you disassemble any binary you want, and provide you all the information about... Read more
Slack 2.6.2 - Collaborative communicatio...
Slack is a collaborative communication app that simplifies real-time messaging, archiving, and search for modern working teams. Version 2.6.2: Fixed Inexplicably, context menus and spell-check... Read more

Latest Forum Discussions

See All

The best new games we played this week
We were quite busy this week. A bunch of big mobile games launched over the past few days, alongside a few teeny surprises. There're lots of quality games to load your phone with. We've gone and picked out five of our favorites for the week. [... | Read more »
Magikarp Jump beginner's guide
Magikarp Jump is a mystifying little game. Part Tamagotchi, part idle clicker, there's not a whole lot of video game there, per se, but for some reason we can't help coming back to it again and again. Your goal is to train up a little Magikarp to... | Read more »
Goat Simulator PAYDAY (Games)
Goat Simulator PAYDAY 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: ** IMPORTANT - SUPPORTED DEVICES **iPhone 4S, iPad 2, iPod Touch 5 or better Goat Simulator: Payday is the most... | Read more »
GRID Autosport delayed until autumn
Sorry mobile racing fans -- GRID Autosport has been delayed a few months. The game is now expected to launch this fall on iOS. Feral Interactive announced that they wanted more time to work on the game's UI and overall performance before launching... | Read more »
Zombie Gunship Survival Beginner's...
The much anticipated Zombie Gunship Survival is here. In this latest entry in the Zombie Gunship franchise, you're tasked with supporting ground troops and protecting your base from the zombie horde. There's a lot of rich base building fun, and... | Read more »
Mordheim: Warband Skirmish (Games)
Mordheim: Warband Skirmish 1.2.2 Device: iOS Universal Category: Games Price: $3.99, Version: 1.2.2 (iTunes) Description: Explore the ruins of the City of Mordheim, clash with other scavenging warbands and collect Wyrdstone -... | Read more »
Mordheim: Warband Skirmish brings tablet...
Legendary Games has just launched Mordheim: Warband Skirmish, a new turn-based action game for iOS and Android. | Read more »
Magikarp Jump splashes onto Android worl...
If you're tired ofPokémon GObut still want something to satisfy your mobilePokémon fix,Magikarp Jumpmay just do the trick. It's out now on Android devices the world over. While it looks like a simple arcade jumper, there's quite a bit more to it... | Read more »
Purrfectly charming open-world RPG Cat Q...
Cat Quest, an expansive open-world RPG from former Koei-Tecmo developers, got a new gameplay trailer today. The video showcases the combat and exploration features of this feline-themed RPG. Cat puns abound as you travel across a large map in a... | Read more »
Jaipur: A Card Game of Duels (Games)
Jaipur: A Card Game of Duels 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: ** WARNING: iPad 2, iPad Mini 1 & iPhone 4S are NOT compatible. ** *** Special Launch Price for a limited... | Read more »

Price Scanner via

Memorial Day savings: 13-inch Touch Bar MacBo...
B&H Photo has the 2016 Apple 13″ Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 13″ 2.9GHz/512GB... Read more
Apple refurbished 13-inch MacBook Airs availa...
Apple has Certified Refurbished 2016 13″ MacBook Airs available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: - 13″ 1.6GHz/8GB/128GB MacBook Air: $... Read more
Apple restocks refurbished 11-inch MacBook Ai...
Apple has Certified Refurbished 11″ MacBook Airs (the latest models recently discontinued by Apple), available for up to $170 off original MSRP. An Apple one-year warranty is included with each... Read more
12-inch 1.2GHz Retina MacBooks on sale for up...
B&H has 12″ 1.2GHz Retina MacBooks on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 12″ 1.2GHz Space Gray Retina MacBook: $1449.99 $150 off... Read more
15-inch 2.7GHz Silver Touch Bar MacBook Pro o...
MacMall has the 15-inch 2.7GHz Silver Touch Bar MacBook Pro (MLW82LL/A) on sale for $2569 as part of their Memorial Day sale. Shipping is free. Their price is $230 off MSRP. Read more
Free Tread Wisely Mobile App Endorsed By Fath...
Just in time for the summer driving season, Cooper Tire & Rubber Company has announced the launch of a new Tread Wisely mobile app. Designed to promote tire and vehicle safety among teens and... Read more
Commercial Notebooks And Detachable Tablets W...
Worldwide shipments of personal computing devices (PCDs), comprised of traditional PCs (a combination of desktop, notebook, and workstations) and tablets (slates and detachables), are forecast to... Read more
Best value this Memorial Day weekend: Touch B...
Apple has Certified Refurbished 2016 15″ and 13″ MacBook Pros available for $230 to $420 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: - 15″ 2.6GHz... Read more
13-inch MacBook Airs on sale for up to $130 o... has 13″ MacBook Airs on sale for up to $130 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (sku MMGF2LL/A): $869.99 $130 off MSRP - 13″ 1.6GHz/256GB MacBook Air (sku... Read more
2.8GHz Mac mini available for $973 with free...
Adorama has the 2.8GHz Mac mini available for $973, $16 off MSRP, including a free copy of Apple’s 3-Year AppleCare Protection Plan. Shipping is free, and Adorama charges sales tax in NY & NJ... Read more

Jobs Board

*Apple* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
Best Buy *Apple* Computing Master - Best Bu...
**509643BR** **Job Title:** Best Buy Apple Computing Master **Location Number:** 001482- Apple Valley-Store **Job Description:** **What does a Best Buy Apple Read more
*Apple* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
*Apple* Mac and Mobility Engineer - Infogrou...
Title: Apple Mac and Mobility Engineer Location: Portland, OR Area Type: 12 month contract Job: 17412 Here's a chance to take your skills to the limit, learn new Read more
*Apple* Retail - Multiple Positions, White P...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.