Advanced programming tips, tricks and hacks for Mac development in C/Objective-C and Cocoa.

Method invocation formatting styles in Objective-C

While most traits of Objective-C follow consistent styles, method invocation formatting — arguably a defining characteristic of the language — does not. In this post, I'll look at a handful of approaches that different programmers use to format their method invocations and discuss their advantages and disadvantages.

The problems with method invocations...

How should you format a method invocation when it is too long to fit on the line? Judging from the multitude of conventions that different programmers use, there is no clear answer.

There is no ambiguity about how to write a short, simple method invocation:

[myColor set];

But if a method is longer than the nominated screen width:

NSColor *myColor = [NSColor colorWithCalibratedRed:120.0/255.0 green:120.0/255.0 blue:120.0/255.0 alpha:1.0];

opinions begin to vary.

In addition to this consideration is how much should you inline? Cocoa strongly suggests that an allocation and initialization statement should always be a single line:

id myObject = [[MyClass alloc] init];

but how far should you continue to inline before decomposing the statement into separate statements? i.e.

// Completely inline...
NSColor *deviceColor = [[[NSColorPicker sharedColorPicker] color] colorUsingColorSpaceName:NSDeviceRGBColorSpace];

// Decomposed...
NSColor *cur = [[NSColorPicker sharedColorPicker] color];
NSColor *devColor = [cur colorUsingColorSpaceName:NSDeviceRGBColorSpace];

Here are a few different approaches...

Style 1: Soft wrap and never decompose

The simplest approach to formatting Objective-C method invocations is the "do nothing" approach. This involves:

  • Make your text editor wrap lines with an indent if they are wider than the page
  • Never decompose statements if the sub-methods are only used once.

Using this approach, the deviceColor creation might look like this:

NSColor *deviceColor = [[[NSColorPicker sharedColorPicker] color]
    colorUsingColorSpaceName:NSDeviceRGBColorSpace];

This is the approach advocated by Penny Arcade recurring character Wil Shipley in his Pimp My Code series. It is also the approach that Apple have started using in some (but not all) of Xcode's project templates.

Advantages

You, as the typer of code, never have to do anything. No fussing, no reformatting. You also never have to declare a variable that you only need once; just inline everything.

For Apple, providing code in a template, this approach also has the advantage that if users prefer wrapped code, it is faster for Xcode users to reformat this unwrapped style into a wrapped style of their choice than it is to reformat already wrapped code into a different style.

Disadvantages

This approach can reduce clarity.

From Pimp My Code Part 5: Special Apple Sample Code Edition...:

    return [[NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,
        NSUserDomainMask, YES) objectAtIndex:0] 
        stringByAppendingPathComponent:[[NSProcessInfo processInfo]
        processName]];

A statement like this is not for everyone. Personally, when I'm starting to lose focus on the code after a few hours at the keyboard, I can't read this well. The visual hierarchy of the statement doesn't follow the structure it contains. A missing or redundant element could be hiding anywhere.

There is also a lack of interoperability with this approach. To anyone reading your code in a non-wrapping editor, the code is significantly less legible. For this reason code is sometimes formatted in the same way but hard-wrapped at 80 characters.

Style 2: Left align all parameters at the same level

For the myColor creation statement that I showed earlier, left aligning all parameters would result in the following:

NSColor *myColor =
    [NSColor
        colorWithCalibratedRed:120.0/255.0
        green:120.0/255.0
        blue:120.0/255.0
        alpha:1.0];
Advantages

Visual structure follows statement structure resulting in high readability. Highly effective for methods with long parameter lists. This approach is also sympathetic to common C and C++ code formatting styles.

Minor variations on this style are excellent for formatting structured inline data. i.e.

NSDictionary *myDictionary =
    [NSDictionary dictionaryWithObjectsAndKeys:
        [NSArray arrayWithObjects:
            [NSDictionary dictionaryWithObjectsAndKeys:
                @"value1", @"key1",
                @"value2", @"key2",
                @"value3", @"key3",
            nil],
        nil], @"keyForArray",
        @"topLevelValue1", @"topLevelKey1",
        @"topLevelValue2", @"topLevelKey2",
    nil];
Disadvantages

Relative to soft-wrap in your text editor, this approach has a high code formatting and maintenance cost. There's a lot of tabs, returns and whitespace to type, delete and move.

Dogmatically applying this style to complexly structured statements can result in poor results. For example, the Pimp My Code sample rigourously formatted in this way:

    return
        [[NSSearchPathForDirectoriesInDomains(
                    NSApplicationSupportDirectory,
                    NSUserDomainMask,
                    YES)
                objectAtIndex:0] 
            stringByAppendingPathComponent:
                [[NSProcessInfo processInfo]
                    processName]];

Style 3: Some left align, some decompose

A more balanced variation on the previous formatting, this approach makes the following changes:

  • Decompose the self access/creation if it can't be performed on one line
  • Only begin wrapping a sub-statement if it can't fit on its line
  • Put the self component of the invocation on the same line as the assignment or return operator (optional)

The sample taken from Pimp My Code would now become:

    NSArray *searchPath = NSSearchPathForDirectoriesInDomains(
        NSApplicationSupportDirectory,
        NSUserDomainMask,
        YES);
    return [[searchPath objectAtIndex:0]
        stringByAppendingPathComponent:
            [[NSProcessInfo processInfo] processName]];
Advantages

Handles compound statements better than dogmatic alignment of every single parameter yet retains much of the structural clarity. Decomposing self access, rather than wrapping it, makes the "subject" of the statement more clear.

Disadvantages

Requires a few judgement calls to be made about when to decompose and when to begin wrapping a statement.

Can have the highest code-formatting maintenance requirements of the styles listed so far, since choosing to decompose or reintegrate elements is time-consuming.

Style 4: Column alignment

This relates to various method invocation formatting styles which attempt to align columns of wrapped data within their lines, including alignment on the colon character:

      [object methodWithParam:theParam
                      another:theOtherValue
                    something:theSomethingValue
                         else:theElseValue];

From my perspective, I don't see people write this type of invocation much anymore, so it seems to me like an "old way of doing things". However the support is in Xcode to help you with this (Preferences->Indentation->Syntax Aware Indenting->":").

I've also seen the following style used:

    [someObject       instanceMethod:   parameter];
    [differentObject  otherMethod:      anotherParameter];

which is an attempt to tab-align every single component on the line.

Advantages

If you are strongly particular about alignment, then maybe this is for you.

Disadvantages

It is doubtful that the end-result in these cases justifies the effort to generate and maintain them. There is text editor support for some of these alignments but it still requires maintenance.

These approaches are also incompatible with any sub-statements that need to be wrapped and so require near-complete decomposition.

Conclusion

If you look at my code, I clearly use something approximating "Style 3", with ad hoc variations depending on how I'm feeling. After years of working in offices with strict coding standards, it seems odd that I don't maintain greater attention to detail but there it is.

There are certainly times when I've considered changing my style to soft-wrapped. Reformatting code because you're changing a line or you decide it's unwieldy is annoying (although I doubt that it actually consumes as much time as it seems).

Soft-wrapped code also appears to be the direction that Apple are heading and they tend to drag a lot of Mac programmers along in their wake.

At this time, I don't find wrapped code to be a pleasing enough aesthetic, so I continue to endure the burden of formatting.

Automated user interface testing on the iPhone

Automated testing of application user interfaces can be tricky since user interfaces are designed for use by humans not automated tools. The iPhone is particularly challenging since existing tools that aid user interface testing on the Mac are not available. This post will show you a way to run automated, scripted tests on an iPhone app's user interface.

Update 2009-08-15: Updated to work with iPhone SDK 3.0.

A warning before we begin...

This post makes use of code from my earlier post Synthesizing a touch event on the iPhone. For this reason, I will restate the warning from that post.

Synthesizing a touch is for debugging and testing only. Do not submit this code in an application to the App Store. Doing so will likely result in:

  • A bad UI experience for your users.
  • An app that breaks on every OS update.
  • Rejection of your application.

Automated user interface testing should always be done in a separate target and the testing code should be exclusive to that target and never submitted to Apple. I don't want to see your projects break or be rejected because you're trying to invoke use undisclosed APIs in your final application.

Challenges for user interface testing on the iPhone

Testing the user interface of an app on the iPhone presents three key challenges:

  • How do you "read" the contents of the user interface?
  • How do you manipulate the user interface?
  • How do you programmatically invoke an iPhone application?

Scenario

I'm going to address the challenges listed above by demonstrating an automated test on the following program:

selftestscreenshot.png

I want to test the following:

    Navigate to "Page 1" and ensure that the UILabel reads "Button clicked on: Page 1" after the "Click me" button is pressed.

To test this, I will create a special Target in the Xcode project that will embed a few extra classes that will run a script. It won't be a "scripting language", merely a data-driven set of commands that the program will run to interrogate itself. This script will perform the work required to navigate the user interface and check that appropriate objects exist and values are set as required.

For the complete implementation, download the "SelfTesting" project (44kb).

Note: this test implementation presented in this Project is not a "unit test", rather it will be a command-line invocation that produces either an empty file (success) or a file containing an error message (failure). A unit test would need to wrap this invocation and interpret the result appropriately.

Interrogating the user interface

The key task that the script will perform is interrogation and manipulation of the user interface. To that end, it must have the ability to read the current state of the user interface and select an object contained within.

Getting the complete user interface state

Generating a description of the user interface is very simple, since all elements descend from UIView. All we have to do is create a category on UIView containing the following:

- (NSMutableDictionary *)fullDescription
{
    NSDictionary *frame =
        [NSDictionary dictionaryWithObjectsAndKeys:
            [NSNumber numberWithFloat:self.frame.origin.x], @"x",
            [NSNumber numberWithFloat:self.frame.origin.y], @"y",
            [NSNumber numberWithFloat:self.frame.size.width], @"width",
            [NSNumber numberWithFloat:self.frame.size.height], @"height",
        nil];
    NSMutableDictionary *description =
        [NSMutableDictionary dictionaryWithObjectsAndKeys:
            [NSNumber numberWithInteger:(NSInteger)self], @"address",
            NSStringFromClass([self class]), @"className",
            frame, @"frame",
            [NSNumber numberWithInteger:[self tag]], @"tag",
            [self valueForKeyPath:@"subviews.fullDescription"], @"subviews",
        nil];
    
    if ([self respondsToSelector:@selector(text)])
    {
        [description
            setValue:[self performSelector:@selector(text)]
            forKey:@"text"];
    }
    if ([self respondsToSelector:@selector(title)])
    {
        [description
            setValue:[self performSelector:@selector(title)]
            forKey:@"title"];
    }
    if ([self respondsToSelector:@selector(currentTitle)])
    {
        [description
            setValue:[self performSelector:@selector(currentTitle)]
            forKey:@"currentTitle"];
    }
    
    return description;
}

This method can then be invoked on any UIView object to get a description of it and all its children. The description includes class name, position, address in memory and all subviews.

By invoking the following:

NSDictionary *currentUserInterfaceState =
        [[[UIApplication sharedApplication] keyWindow] fullDescription];

we get a description of the keyWindow (i.e. the current visible window).

Selecting objects within this user interface description

The next requirement is to select the objects that interest us. To do this, I chose to convert the NSDictionary representation of the user interface to XML and select elements using XPath queries.

Using the iPhone XPath query code that I presented in my earlier post titled "Using libxml2 for XML parsing and XPath queries in Cocoa", selecting a set of matching UIViews from the full collection of views on screen looks like this:

    NSDictionary *keyWindowDescription =
        [[[UIApplication sharedApplication] keyWindow] fullDescription];
    NSData *resultData =
        [NSPropertyListSerialization
            dataFromPropertyList:keyWindowDescription
            format:NSPropertyListXMLFormat_v1_0
            errorDescription:nil];

    NSArray *queryResults = PerformXMLXPathQuery(resultData, xpath);

The XPath queries to select views in this way are a little cumbersome, due to the "sequential nodes" arrangement of key-value pairs in a Property List. A demonstration of how a query to choose the UIRoundedRectButton on screen with the currentTitle "Click Me" would be:

//dict[key[.='className' and following-sibling::string[1]/.='UIRoundedRectButton'] and key[.='currentTitle' and following-sibling::string[1]/.='Click me']]

More stealing from myself: manipulating the user interface

The only form of user interface manipulation required for this case is touches. The code for this can be found in my earlier post: "Synthesizing a touch event on the iPhone".

Previously, the code from that post didn't always work. There were multiple problems with the original implementation due to the limitations of working with undocumented features of the iPhone SDK. These problems got worse with the iPhone SDK 2.2 that Apple released this week.

I've gone back and fixed the code from the "Synthesizing a touch event on the iPhone". It should work reliably in most situations now, including as the "user interface manipulation" part of this post's test scripting environment.

Running script commands

The "script" that the test will run is just an NSArray of NSDictionary objects contained in a Property List file.

selftestscript.png

The class that handles this script is ScriptRunner in the project.

When the project is compiled with SCRIPT_DRIVEN_TEST_MODE_ENABLED defined (i.e. when the "TestScriptRunner" target is selected) an object of this class is created in the -applicationDidFinishLaunching: method. Once every two seconds, the ScriptRunner selects the next command and invokes the appropriate action. This delay is inserted to allow user interface animations to occur.

Note: you may notice the "scrollToRow" command. This command is required because rows that are not visible in a UITableView do not have a corresponding UITableViewCell in the view hierarchy. We must scroll to a row before attempting to send a touch event to it.

Configuring the project and command-line execution

A testing Target

Since we don't want any of the test code in our program normally, the project file should contain a separate Target for testing. No other Target should include the test classes. The script itself (a Property List file named "TestScript.plist") is similarly excluded from non-testing Targets.

The testing Target should have the "Base SDK" in its settings set to "Simulator" (whichever OS version you want).

Further, the testing Target will define the preprocessor macro SCRIPT_DRIVEN_TEST_MODE_ENABLED which will be used to conditionally construct and start the ScriptRunner object. This must be set in the Target Settings (editing the Project Settings will affect all Targets).

Auto-run build step

The only remaining addition to the project is a build step that will run the project in the simulator when the Target is built.

I borrow this technique from the Google Toolbox for Mac on their iPhoneUnitTesting wiki page.

A "Run Script" build phase is added to the Target as the last step. The script I use is:

export DYLD_ROOT_PATH="$SDKROOT"
export DYLD_FRAMEWORK_PATH="$CONFIGURATION_BUILD_DIR"
export IPHONE_SIMULATOR_ROOT="$SDKROOT"
export CFFIXED_USER_HOME="$USER_LIBRARY_DIR/Application Support/iPhone Simulator/User"
"$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -RegisterForSystemEvents 2> "$PROJECT_DIR/errorLogFromLastBuild.txt"

This script sets the environment variables so that a simulator build of the project can be invoked directly (last line of the script). I also redirect stderr to the file errorLogFromLastBuild.txt in the base directory of the Project. If this file has non-zero contents, then the test script failed.

Invoking the build and test for the testing target named "TestScriptRunner" is then achieved by invoking the following shell command from the same directory as the Project:

xcodebuild -configuration "Release" -target "TestScriptRunner"

If errorLogFromLastBuild.txt is empty after the script has finished, then the test succeeded.

Running the program in this manner will not show a user interface. This may seem weird, especially given that it's a user interface test. This "headless" invocation will still run correctly, despite the lack of the Simulator window.

Podcast update

If you'd like to hear more about this topic, you can listen to the January 19, 2009 podcast interview I gave to Dan Grigsby of Mobile Orchard about the development of the project.

Conclusion

This final solution presented in the SelfTesting Project can be scripted to perform navigation of a user interface as well as queries and testing of the views within that user interface.

The current implementation is only intended for running one test per invocation. This approach is recommended because it resets the user interface state between tests. It does mean that running different tests involves swapping in a new TestScript.plist file each time.

Testing of more sophisticated classes with more complex state would require further command names added to the script's language and greater amounts of data extracted by -[UIView fullDescription]. It should be easy to add such features as required.

Finally, remember to keep your user interface testing code in a separate target (with testing files excluded from your main application target) so it isn't included in the application you submit to the App Store.

Singletons, AppDelegates and top-level data.

If you require only a single instance of an object in your application, where should it go? How should you control and manage it? Here are some different approaches, their implementations, their strengths and their weaknesses.

A little about global variables

They should scare you

Global variables is a term that invokes a sense of dread in experienced programmers. They are feared because a program filled with global variables (when it should use scoped variables instead) is a program without structure; a totally unmanageable mess.

This post will be entirely about writing and using global variables.

They're essential

The reality is that applications need to have some global state; we must have global variables. A variable will need to be global if all of the following are true:

  1. No other object owns, manages or is otherwise responsible for it
  2. There is exactly one in the whole program
  3. It is not a constant (like a string or number)

If all of these are true, then you should use a global variable.

If you're wondering, variables that fall outside these rules should be (respectively):
  1. child variables of the object that manages them
  2. children of the object that manages the collection
  3. a #define or a const (constants are state for the compiler, not the program)
In Cocoa, they're not quite global

Actually, what I will be showing are the "in practice" global variables of a Cocoa program — in reality, none of the techniques I show you will be true global variables in the Standard C Language sense but these approaches have replaced true global variables in Cocoa programs in almost all cases.

I will be showing you top-level child objects (children of the application delegate) and singleton objects. Explaining why these are normally considered equivalent to globals:

  • The application object is the first constructed object in the program from which all other hierarchically arranged objects are constructed, making it effectively the top-level scope in the program (like a global scope). The application delegate should be considered a basic extension of the application object itself (especially since you should never override the application class).
  • A singleton is an object that can be allocated only once (and can't be deleted) — making it a single, global instance. While singletons are stored in a true global variable, they are never accessed that way in Objective-C (a class method is used to access them), providing a least some abstraction around the implementation.

AppDelegates and AppControllers

As every Cocoa programmer knows, an application delegate is created in the MainMenu.xib file:

appdelegatecreation.png

or the MainWindow.xib file for the iPhoneSDK.

A globally accessed variable can be initialized in the applicationDidFinishLauching delegate method:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    myGlobalObject = [[MyGlobalObject alloc] init];
}

and assuming myGlobalObject has an associated getter method, you can now access it globally using:

[[NSApp delegate] myGlobalObject]

or on the iPhone:

[[UIApplication sharedApplication].delegate myGlobalObject]

Since the delegate property returns an id (instead of the actual class of your delegate), you can't use property notation for the myGlobalObject itself unless the myGlobalObject is a property and you wrap the delegate in parentheses and inside the parentheses cast the delegate to your application delegate's class, like this:

((MyAppDelegate *)[UIApplication sharedApplication].delegate).myGlobalObject

Although I have seen people declare the following macro in their delegate's header:

#define UIAppDelegate \
    ((MyAppDelegate *)[UIApplication sharedApplication].delegate)

which then allows you to use:

UIAppDelegate.myGlobalObject

from anywhere that includes your delegate's header.

Why AppDelegates are bad

Having explained that the above could be done, I will tell you that in my programs, I avoid using the AppDelegate for anything other than:

  • implemenations of the NSApplication delegate methods (including applicationDidFinishLaunching: to finalize application construction)
  • handling menu items for items that don't exist in a window (for example, opening the application Preferences window)

Relying on your AppDelegate object to manage your global variables can quickly get scary for the same reason that global variables in general are considered scary: you can easily put too much into this top level and it becomes a big, unstructured mess. This problem is an anti-pattern, often called the Big Ball of Mud.

It is a bad idea structurally for two reasons. The first is encapsulation. The AppDelegate should only really be connected to things related to the AppDelegate (i.e. the NSApplication object and related state). If you store data related to other objects inside the AppDelegate, you rob those other objects of control over themselves.

Separation of concerns is the other serious problem. It is not the application delegate's responsibility to be the gatekeeper and manager of non-Application-related variables within the program.

A well-designed program organizes its classes so that they are all discrete, self-contained entities, shoving connections to everything into the AppDelegate violates this idea.

Singletons in Cocoa

The solution to the encapsulation problem is to create classes that manage any global data as discreet modules. This is done through a singleton.

The basic recipe for making a singleton is given by Apple: Creating a Singleton Instance.

I personally like to put these singleton methods into a macro, which you can download in my CWLSynthesizeSingleton.h file. If you #import this header at the top of a class implementation, then all you need to do is write:

CWL_SYNTHESIZE_SINGLETON_FOR_CLASS(MyClassName);

inside the @implementation MyClassName declaration and your class will become a singleton. You will also need to add the line:

CWL_DECLARE_SINGLETON_FOR_CLASS(MyClassName)

in the method declarations section of the header file for MyClassName so the singleton accessor method can be found from other source files if they #import the header.

Once your class is a singleton, you can access the instance of it using the line:

[MyClassName sharedMyClassName];
Note: A singleton does not need to be explicitly allocated or initialized (the alloc and init methods will be called automatically on first access) but you can still implement the default init method if you want to perform initialization.

Advantages of a singleton

A well-designed singleton is a discrete, self-managing object that manages a specific role within your program.

Variables hung off the Application delegate should be limited to objects that relate to the Application delegate in some way. A singleton should be entirely focussed on its own specific role and responsibilities. To avoid the anti-pattern known as "coupling" your singletons should have zero (or practically zero) connections to the rest of your program — they should be stand-alone little pockets of functionality.

Search the Mac OS X Reference in XCode for methods that begin with "shared" to see the ways in which Apple use singletons to create "manager" objects which allow you to get, set and manipulate entities that exist only once in a program.

Also, since the singleton is accessed through a method, there is some abstraction around the specific implementation — you could move from a true singleton to a per-thread based implementation if you needed, without changing the external interface.

Conclusion

Don't use globals unless you need to do so. An overwhelming majority of the data in your program has a sensible parent that is not the top-level. Singletons and top-level data should be used only when the data they contain truly belongs at the top level.

Cocoa singletons are flexible and useful when you need them. Using your application delegate to hold top-level data will work but try to limit its responsibilities to MainMenu.xib allocated objects where possible.

Simplifying your code using NSDictionary

Computers programs are good at mindless repetitive tasks, they are not good at broad decision trees. In this post, I will show you a way of eliminating conditionals from your code that are based on program state by using an array of NSDictionary objects to maintain state.

Introduction

In general, the more code branches a computer program has, the harder it is to write and the harder it is to test and maintain.

Comparatively, data tends to be easier to write. When separated from the code that processes it, data can also allow for cleaner design — placing dependent values together, and removing the complexity of the data from the structure of the code.

This is not a novel idea but I think it is a really useful technique that programmers too-often forget. The general idea is not specific to NSDictionary but due to NSDictionary's flexibility and broad support in Cocoa, it is an excellent choice for the task.

The sample program

Download the XCode 3.1 project file for the sample program here (62kB).

To illustrate this and show ways of overcoming conditionals and complexity, I will present the following program:

state_one.png

This program has two state variables:

  • The popup menu (with the two states "Square" and "Triangle")
  • The checkbox (again, two states)

The state of these controls affects:

  • the shape drawn in the window
  • the color of the shape
  • the direction that the red circle animates around the shape
  • whether the shape is filled or drawn as a border only
  • the label under the shape (which is dependent on both controls)

Writing the behavior in code for every state results in at least 5 places in the program dependent on the state of these controls and conditionals with different branches at each of these points.

If the program is extended with more states added to the popup menu, this would result in further conditionals at every single one of these points, causing an increase in program complexity with each new item.

Lots of conditionals and data embedded in code

The code in the program that returns the "Animating around four points, anti-clockwise" label looks like this:

if ([[self stateName] isEqual:@"Square"])
{
    if (self.clockwise)
    {
        return @"Animating around four points, clockwise";
    }
    else
    {
        return @"Animating around four points, anti-clockwise";
    }
}
else if ([[self stateName] isEqual:@"Triangle"])
{
    if (self.clockwise)
    {
        return @"Animating around three points, clockwise";
    }
    else
    {
        return @"Animating around three points, anti-clockwise";
    }
}

You can see that if the number of items in the popup menu were doubled, it would double the size of this code.

The branches in this code exist because the text of the label is a piece of dependent state. The state of the popup menu implicitly affects the text of the label. Unfortunately, changing the popup menu is only changing a single string value (the "stateName") — we are forced to generate the dependent values from this throughout the code.

Eliminating conditionals and removing the data from the code

Programming languages are literal beasts and they work better when the code (and the relationships within it) are explicitly defined. So we need a way to explicitly describe all of the dependent properties and associate these properties with the popup menu states upon which they depend.

In replacing the above code fragment, the text of the label must exist somewhere — nothing will make that requirement go away — but we can remove the hard work from the code by using an NSDictionary created from a PropertyList file that looks like this:

stateplist.png

We will bind the content of the popup menu to this array of NSDictionary and make each item in the popup menu get its name from the "stateName" value in each NSDictionary.

The result from doing this is that the above code fragment to fetch the current label becomes:

return [self.selectedItem objectForKey:[self clockwiseKey]];

We have traded complexity of code for volume of data. Since it is normally considered simpler to generate hundreds of rows of data than hundreds of blocks of code, this is a good trade-off. Moving the data from the program out of the code and into a common place also has advantages for managing, understanding and designing our program as a whole.

Method choices can go into data too

In the program, the "Square" is drawn by filling in an NSBezierPath. The "Triangle" is drawn as just a border.

Different methods are invoked to achieve these two options. Without the state NSDictionary, the code would look like this:

if ([[stateController stateName] isEqual:@"Square"])
{
    [path fill];
}
else if ([[stateController stateName] isEqual:@"Triangle"])
{
    [path stroke];
}

Even this choice between two different pieces of code can be moved into the data because of Objective-C's ability to lookup selectors at runtime:

SEL drawSelector = NSSelectorFromString(
    [stateController.selectedItem objectForKey:@"drawSelector"]);
[path performSelector:drawSelector withObject:nil];

Again, all conditionals are gone; every choice dependent on state has been moved into the data instead.

Limitations

The biggest limitation of this approach to program design is the complexity of the data itself. Moving values, rules and dependencies into a data file is good, until the structure of the data becomes complex enough that it amounts to a programming language itself and you're no longer reducing the complexity of the code+data as a whole.

The data itself may also need some management. Loading of the data is simple if you are using a generic file format (like a PropertyList) but generic formats won't provide ideal storage for your data types.

To show how working with the data format can become burdensome, let's take a look at the hard-coded version of the program setting the drawing color:

if ([[stateController stateName] isEqual:@"Square"])
{
    [[NSColor colorWithCalibratedRed:061.0/255.0 green:187.0/255.0 blue:056.0/255.0 alpha:122.0/255.0] set];
}
else if ([[stateController stateName] isEqual:@"Triangle"])
{
    [[NSColor colorWithCalibratedRed:187.0/255.0 green:056.0/255.0 blue:186.0/255.0 alpha:122.0/255.0] set];
}

With only two colors enumerated in code, this is arguably simpler than loading the same values from the NSDictionary:

NSDictionary *drawColor = [stateController.selectedItem objectForKey:@"drawColor"];
[[NSColor
    colorWithCalibratedRed:[[drawColor objectForKey:@"red"] doubleValue]
    green:[[drawColor objectForKey:@"green"] doubleValue]
    blue:[[drawColor objectForKey:@"blue"] doubleValue]
    alpha:[[drawColor objectForKey:@"alpha"] doubleValue]]
set];

Since a PropertyList doesn't hold NSColor directly, we must break the color up into its components for the PropertyList and construct the color from the components when we need it.

Remember, despite the added complexity of loading the values here, the key advantage of the from-NSDictionary version is that it will scale better; the from-NSDictionary version won't require further code if further options are added to the popup menu.

Conclusion

The sample program contains both hard-coded and from-NSDictionary implementations. With only two top-level states ("Square" and "Triangle") these two implementations contain roughly the same amount of code overall (when the loading of the PropertyList is taken into consideration).

It is clear though that the from-NSDictionary version would scale far better — it would require no more code to handle a dozen options in the popup menu, whereas the hard-coded version would be almost six times bigger.

The from-NSDictionary version also allows you to see the program in a different way. It is subjective but I think that seeing the different properties associated with each state fully enumerated in the PropertyList makes the operation of the program easier to understand.