How to handle Xcode in your meta-build system’s iOS or Mac app target

OK, I’ve said before in APPropriate Behaviour that I dislike build systems that build other build systems:

Some build procedures get so complicated that they spawn another build system that configures the build environment for the target system before building. An archetypal example is GNU autotools – which actually has a three-level build system. Typically the developers will run `autoconf`, a tool that examines the project to find out what questions the subsequent step should ask and generates a script called `configure`. The user downloads the source package and runs `configure`, which inspects the compilation environment and uses a collection of macros to create a Makefile. The Makefile can then compile the source code to (finally!) create the product.

As argued by Poul-Henning Kamp, this is a bad architecture that adds layers of cruft to work around code that has not been written to be portable to the environments where it will be used. Software written to be built with tools like these is hard to read, because you must read multiple languages just to understand how one line of code works.

One problem that arises in any cross-platform development is that assumptions about “the other platforms” (being the ones you didn’t originally write the software on) are sometimes made based on one of the following sources of information:

  • none
  • a superficial inspection of the other platform
  • analogy to the “primary” platform

An example of the third case: I used to work on the Mac version of a multi-platform product, certain core parts of which were implemented by cross-platform libraries. One of these libraries just needed a little configuration for each platform: tell it what file extension to use for shared libraries, and give it the path to the Registry.

What cost me a morning today was an example of the second case: assuming that all Macs are like the one you tried. Let me show you what I mean. Here’s the contents of /Developer on my Mac:

$ ls /Developer/
WebObjects

Wait, where’s Xcode? Oh right, they moved it for the App Store builds didn’t they?

$ ls /Applications/Xcode.app
ls: /Applications/Xcode.app: No such file or directory

WHAAAAA?

OMFG!

Since Xcode 2.5, Xcode has been relocatable and can live anywhere on the filesystem. Even if it is in one of the usual places, that might not be the version a developer wants to use. I keep a few different Xcodes around: usually the current one, the last one I knew everything worked on, and a developer preview release when there is one. I then also tend to forget to throw old Xcodes away, so I’ve got 4 different versions at the moment.

But surely this is all evil chaos from those crazy precious Mac-using weirdos! How can you possibly cope with all of that confusion? Enter xcode-select:

$ xcode-select -print-path
/Applications/Xcode4.6.app/Contents/Developer

Xcode-select is in /usr/bin, so you don’t have the bootstrapping problem of trying to find the tool that lets you find the thing. That means that you can always rely on it being in one place for your scripts or other build tools. You can use it in a shell script:

XCODE_DEVELOPER_DIR=`/usr/bin/xcode-select -print-path`

or in a CMake file:

exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE XCODE_DEVELOPER_DIR)

or in whatever other tool you’re using. The path is manually chosen by the developer (using the -switch option), so if for some reason it doesn’t work out (like the developer has deleted that version of Xcode without updating xcode-select), then you can fall back to looking in default locations.

Please do use xcode-select as a first choice for finding Xcode or the developer folder on any Mac system, particularly if your project uses a build generator. It’s more robust to changes—either from Apple or from the users of that Mac—than relying on the developer tools being installed to their default location.

Sideloading content into iOS apps

All non-trivial apps visualise content in some form, whether it’s game levels embedded in the app, data loaded from some internet service, or something else.

In many cases the developer who’s writing the Objective-C code isn’t going to be the person who creates or prepares this content. In the case of embedded content, this can lead to a slow feedback loop—the content experts create a database or some other assets, then send it to the developer. The developer prepares a build using the new assets, uploading it to TestFlight or some other ad-hoc distribution centre. Then the content people can download that app to see their content in the context of the application it’s designed for.

There’s a simple way to close this loop, letting content creators see the app with their latest changes as they make them. That is to use iTunes File Sharing to load the content via the app’s Documents folder.

If you have a line like this:

NSString *pathToContent = [[NSBundle mainBundle] pathToResource: @"myDatabase" ofType: @"sqlite"];

Change it to use a function like this:

NSString *pathToPotentiallySideloadedFile(NSString *filename, NSString *type)
{
    NSString *pathInDocumentsFolder = [[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent: filename] stringByAppendingPathExtension: type];
    if (pathInDocumentsFolder)
        return pathInDocumentsFolder;
    else
        return [[NSBundle mainBundle] pathForResource: filename ofType: type];
}

//...
NSString *pathToContent = pathToPotentiallySideloadedFile(@"myDatabase", @"sqlite");

Now if people working on your app have a file in their Documents folder with the same name as the one used in the app, it’ll load their version. So, how do they get it in there?

You need to make a simple change to your app’s Info.plist:

    <key>UIFileSharingEnabled</key>
    <true/>

Now when anybody with the app connects their device to iTunes, they’ll be able to use file sharing to add their own content. Don’t forget to turn this off before you go live!

I mentioned at the beginning of this post that this technique can be used for networked apps. Obviously there isn’t really any difficulty getting updated content into a network-driven app; or if there is, someone did it wrong.

It’s the opposite problem you have: keeping the content fixed. If your online component—be it a CMS, a data feed from an API, or something else—is getting new data you can’t always ensure that the app is looking at the same stuff in testing. Indeed, sometimes I’ve found the CMS developers changing the data format without telling anyone; if you’re investigating a particular condition related to the state of the data, it can be hard to reproduce.

You can use the iTunes File Sharing technique to load a specific version of the app’s data without relying on the network connection and the server giving you the same output. This is great for regression testing, as you can ensure that only your code is changing between runs.

I made a web!

That is, I made a C program using the literate programming tool, CWEB. The product it outputs is, almost by definition, self-documenting, so find out about the algorithm and how I built it by reading the PDF. This post is about the process.

Unsurprisingly I found it much more mentally taxing to understand a prose description of a complex algorithm and how I might convert that into C than writing the C itself. In that, and acknowledging that this little project was a very artificial example, it was very helpful to be able to write long-form comments alongside the code.

That’s not to say that I don’t normally comment my code; I often do when I’m trying something I don’t think I understand. But often I’ll write out a prose description of what I’m trying to do in a notebook, or produce incredibly terse C comments. The literate programming environment encouraged me to marry these two ideas and create long prose that’s worth reading, but attach it to the code I’m writing.

I additionally found it useful to be able to break up code into segments by idea rather than by function/class/method. If I think “oh, I’ll need one of these” I can just start a new section, and then reference it in the place it’ll get used. It inverts my usual process, which is to write out the code I think I’ll need to do a task and then go back and pick out isolated sections with refactoring tools.

As a developer’s tool, it’s pretty neat too, though not perfect. The ctangle tool that generates the C source code inserts both comments referring to the section of the web that the code comes from, and (more usefully) preprocessor #line directives. If you debug the executable (which I needed to…) you’ll get told where in the human-readable source the PC is sitting, not where in the generated C.

The source file, a “web” that contains alternating TeX and C code, is eminently readable (if you know both TeX and C, obviously) and plays well with version control. Because this example was a simple project, I defined everything in one file but CWEB can handle multiple-file projects.

The main issue is that it’d be much better to have an IDE that’s capable of working with web files directly. A split-pane preview of the formatted documentation would be nice, and there are some good TeX word processors out there that would be a good starting point. Code completion, error detection and syntax highlighting in both the C and TeX parts would be really useful. Refactoring support would be…a challenge, but probably doable.

So my efforts with CWEB haven’t exactly put me off, but do make me think that even three decades after being created it’s not in a state to be a day-to-day developer environment. Now if only I knew someone with enough knowledge of the Clang API to think about making a C or ObjC IDE…

Using GNUstep libraries with Xcode

I was recently asked about building projects that use GNUstep from Xcode. The fact is, it’s incredibly easy.

By default, GNUstep on Mac OS X installs its libraries to /usr/local/lib and its frameworks to /Library/Frameworks. Therefore if you want to include GNUstep-base additions, you just hit the + button in your target’s “link binary with libraries” section and find the libgnustep-baseadd.dylib entry under Mac OS X 10.7. If you wanted to use GNUstepWeb, you’d look for WebObjects.framework in the same list.

You can get access to the GNUstep base additions in your code by including <GNUstepBase/GNUStep.h.

Notice that if you manage a GNUstep project using Xcode, you’ll only be able to build it on a Mac (unless you go to the bother of writing a build tool with GNUstep’s unfortunately-named XCode.framework – which ironically doesn’t currently work on Mac OS X.). If you need to target non-Mac platforms, your options are to build Cocotron-style cross-compilers and add them to your Xcode project, or to create an Xcode project with an External Build System target and manage your build via make anyway.

An interesting extension would be to define a new filesystem layout for GNUstep-make that deposited all of the frameworks and libraries into a .sdk folder that could be used in Xcode as an additional SDK.

Messing about with Clang

I’ve been reading the Smalltalk-80 blue book (pdf) recently, and started to wonder what a Smalltalk style object browser for Objective-C would look like. Not just from the perspective of presenting the information that makes up Objective-C classes in novel ways (though this is something I’ve discussed with Saul Mora at great length in the past). What would an object browser in which the compiler is an object, so you can define and manipulate classes in real time, look like?

Well, the first thing you’d need to do is to turn the compiler into an object. I decided to see whether I could see what the compiler sees, using the clang compiler front-end library.

Wait, clang library? Clang’s a command-line tool, isn’t it? Well yes, but it and the entire of LLVM are implemented as a collection of reusable C++ classes. Clang then has a stable C interface wrapping the C++, and this is what I used to produce this browser app. This isn’t the browser I intend to write, this is the one I threw away to learn about the technology.

Objective-Browser

Clang is a stream parser, and there are two ways to deal with source files just like any other stream: event-driven[*], in which you let the parser go and get callbacks from it when it sees interesting things, or document-based[*] where you let the parser build up a document object model (a tree, in this case) which you then visit the nodes of to learn about the data.

[*] Computer scientists probably call these things something else.

Being perverse, I’m going to use the event-driven parser to build a parallel data model in Objective-C. First, I need to adapt the clang library to Objective-C, so that the compiler is an Objective-C object. Here’s my parser interface:

#import <Foundation/Foundation.h>

@protocol FZAClassParserDelegate;

@interface FZAClassParser : NSObject

@property (weak, nonatomic) id <FZAClassParserDelegate>delegate;

- (id)initWithSourceFile: (NSString *)implementation;
- (void)parse;

@end

The -parse method is the one that’s interesting (I presume…) so we’ll dive into that. It actually farms the real work out to an operation queue:

#import <clang-c/Index.h>

//...

- (void)parse {
    __weak id parser = self;
    [queue addOperationWithBlock: ^{ [parser realParse]; }];
}

- (void)realParse {
#pragma warning Pass errors back to the app
    @autoreleasepool {
        CXIndex index = clang_createIndex(1, 1);
        if (!index) {
            NSLog(@"fail: couldn't create index");
            return;
        }
        CXTranslationUnit translationUnit = clang_parseTranslationUnit(index, [sourceFile fileSystemRepresentation], NULL, 0, NULL, 0, CXTranslationUnit_None);
        if (!translationUnit) {
            NSLog(@"fail: couldn't parse translation unit);
            return;
        }
        CXIndexAction action = clang_IndexAction_create(index);

That’s the setup code, which gets clang ready to start reading through the file. Which is done in this function:

        int indexResult = clang_indexTranslationUnit(action,
                                                     (__bridge CXClientData)self,
                                                     &indexerCallbacks,
                                                     sizeof(indexerCallbacks),
                                                     CXIndexOpt_SuppressWarnings,
                                                     translationUnit);

This is the important part. Being a C callback API, clang takes a context pointer which is the second argument: in this case, the parser object. It also takes a collection of callback pointers, which I’ll show next after just showing that the objects created in this method need cleaning up.

        clang_IndexAction_dispose(action);
        clang_disposeTranslationUnit(translationUnit);
        clang_disposeIndex(index);
        (void) indexResult;
    }
}

There’s a structure called IndexCallbacks defined in Index.h, this class’s structure contains functions that call through to methods on the parser’s delegate:

int abortQuery(CXClientData client_data, void *reserved);
void diagnostic(CXClientData client_data,
                CXDiagnosticSet diagnostic_set, void *reserved);
CXIdxClientFile enteredMainFile(CXClientData client_data,
                                CXFile mainFile, void *reserved);
CXIdxClientFile ppIncludedFile(CXClientData client_data,
                               const CXIdxIncludedFileInfo *included_file);
CXIdxClientASTFile importedASTFile(CXClientData client_data,
                                   const CXIdxImportedASTFileInfo *imported_ast);
CXIdxClientContainer startedTranslationUnit(CXClientData client_data,
                                            void *reserved);
void indexDeclaration(CXClientData client_data,
                      const CXIdxDeclInfo *declaration);
void indexEntityReference(CXClientData client_data,
                          const CXIdxEntityRefInfo *entity_reference);

static IndexerCallbacks indexerCallbacks = {
    .abortQuery = abortQuery,
    .diagnostic = diagnostic,
    .enteredMainFile = enteredMainFile,
    .ppIncludedFile = ppIncludedFile,
    .importedASTFile = importedASTFile,
    .startedTranslationUnit = startedTranslationUnit,
    .indexDeclaration = indexDeclaration,
    .indexEntityReference = indexEntityReference
};

int abortQuery(CXClientData client_data, void *reserved) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParserShouldAbort:)]) {
            return [parser.delegate classParserShouldAbort: parser];
        }
        return 0;
    }
}

// …

Internally clang creates its own threads, so the callback functions wrap delegate messages in @autoreleasepool so that the delegate doesn’t have to worry about this.

The delegate still needs to understand clang data structures of course, this is where the real work is done. Here’s the delegate that’s used to build the data model used in the browser app:

#import <Foundation/Foundation.h>
#import "FZAClassParserDelegate.h"

@class FZAClassGroup;

@interface FZAModelBuildingParserDelegate : NSObject <FZAClassParserDelegate>

- (id)initWithClassGroup: (FZAClassGroup *)classGroup;

@end

The FZAClassGroup class is just somewhere to put all the data collected by parsing the file: in a real IDE, this might represent a project, a translation unit, a framework or something else. Anyway, it has a collection of classes. The parser adds classes to that collection, and methods and properties to those classes:

@implementation FZAModelBuildingParserDelegate {
    FZAClassGroup *group;
    FZAClassDefinition *currentClass;
}

- (id)initWithClassGroup:(FZAClassGroup *)classGroup {
    if ((self = [super init])) {
        group = classGroup;
    }
    return self;
}

- (void)classParser:(FZAClassParser *)parser foundDeclaration:(CXIdxDeclInfo const *)declaration {
    const char * const name = declaration->entityInfo->name;
    if (name == NULL) return; //not much we could do anyway.
    NSString *declarationName = [NSString stringWithUTF8String: name];

We’ve now got a named declaration, but a declaration of what?

    switch (declaration->entityInfo->kind) {
        case CXIdxEntity_ObjCProtocol:
        {
            currentClass = nil;
            break;
        }
        case CXIdxEntity_ObjCCategory:
        {
            const CXIdxObjCCategoryDeclInfo *categoryInfo = 
            clang_index_getObjCCategoryDeclInfo(declaration);
            NSString *className = [NSString stringWithUTF8String: categoryInfo->objcClass->name];
            FZAClassDefinition *classDefinition =[group classNamed: className];
            if (!classDefinition) {
                classDefinition = [[FZAClassDefinition alloc] init];
                classDefinition.name = className;
                [group insertObject: classDefinition inClassesAtIndex: [group countOfClasses]];
            }
            currentClass = classDefinition;
            break;
        }
        case CXIdxEntity_ObjCClass:
        {
            FZAClassDefinition *classDefinition =[group classNamed: declarationName];
            if (!classDefinition) {
                classDefinition = [[FZAClassDefinition alloc] init];
                classDefinition.name = declarationName;
                [group insertObject: classDefinition inClassesAtIndex: [group countOfClasses]];
            }
            currentClass = classDefinition;
            break;
        }

I’m ignoring protocols, but recognising that methods declared in a protocol shouldn’t go onto any particular class. Similarly, I’m adding methods found in categories to the class on which that category is defined: real Smalltalk browsers keep the categories, but for this prototype I decided to skip them. I’m using the fact that this is a prototype to justify having left the duplicate code in place, above :-S.

So now we know what class we’re looking at, we can start looking for methods or properties defined on that class:

        case CXIdxEntity_ObjCClassMethod:
        case CXIdxEntity_ObjCInstanceMethod:
        {
            FZAMethodDefinition *method = [[FZAMethodDefinition alloc] init];
            method.selector = declarationName;
            if (declaration->entityInfo->kind == CXIdxEntity_ObjCClassMethod)
                method.type = FZAMethodClass;
            else
                method.type = FZAMethodInstance;
            [currentClass insertObject: method inMethodsAtIndex: [currentClass countOfMethods]];
            break;
        }
        case CXIdxEntity_ObjCProperty:
        {
            FZAPropertyDefinition *property = [[FZAPropertyDefinition alloc] init];
            property.title = declarationName;
            [currentClass insertObject: property inPropertiesAtIndex: [currentClass countOfProperties]];
            break;
        }
        default:
            break;
    }
}

And that’s “it”. The result of collecting all of these callbacks is a tree:

ClassGroup -> Class -> [Method, Property]

I define a tree-ish interface for all of these classes, by adding categories that define the same methods:

@interface FZAMethodDefinition (TreeSupport)

- (NSInteger)countOfChildren;
- (NSString *)name;
- (id)childAtIndex: (NSInteger)index;
- (BOOL)isExpandable;

@end

@implementation FZAMethodDefinition (TreeSupport)

- (NSInteger)countOfChildren {
    return 0;
}

- (BOOL)isExpandable {
    return NO;
}

- (id)childAtIndex:(NSInteger)index {
    return nil;
}

- (NSString *)name {
    switch (self.type) {
        case FZAMethodClass:
            return [@"+" stringByAppendingString: self.selector];
            break;
        case FZAMethodInstance:
            return [@"-" stringByAppendingString: self.selector];
            break;
        default:
            return [@"?" stringByAppendingString: self.selector];
            break;
    }
}

@end

And, well, that’s it. libClang could be the kernel of a thousand visualizers, browsers and editors for C-derived languages, the start of one is outlined above.

Adding components to a GNUstep web / WebObjects app

In WebObjects, Components take the role of a view controller in what passes for Cocoa’s version of MVC. Each is responsible for calculating the data that the view objects are bound to: you saw an example of this in the previous post. Each is also responsible for responding to user interface events—called actions—and preparing the next component where that’s required.

Navigating between components

Let’s add a new component to our HelloGSW test app. We’ve recorded the date that the visitor arrived at the site, we could (for sake of demonstration, not because it’s useful) find out how long it takes that visitor to get to the next page. We’ll come onto the mechanics of adding it to the project later, but for now we note that we require a way for the visitor to indicate their intention to see the next page. That means, as a simple way to do things, having a form with a submit button.

We could write the form into the HTML, but then we’d have to know what URL the WO machinery was going to use to call our action. So we’ll use WebObjects to generate the form, using this HTML:

 <webobject name=form>
   <webobject name=submit_button><INPUT TYPE="SUBMIT"></webobject>
 </webobject>

As you’ve seen, the data bindings for each webobject need to be defined in the WOD file:

form:WOForm {}
submit_button:WOSubmitButton {action = nextPage}

As with the value binding you saw last time, we can bind the action of the submit button to a method on the component. Those of you who have used Cocoa Bindings may be surprised to find that you can do the same with NSResponder subclasses, though it’s rare to see it done with Mac apps.

So finally, I GIVE YOU TEH CODEZ:

- (GSWComponent *)nextPage {
  ClickDelay *nextComponent = (ClickDelay *)[self pageWithName: @"ClickDelay"];
  nextComponent.startDate = accessedAt;
  return nextComponent;
}

As with view controllers on the iPhone, you just create the new component (-pageWithName: does that, and configures its context correctly) and configure state where appropriate. Unlike with iOS view controllers, you don’t specify how they get presented because there’s only one way that will (probably) ever happen: in an HTTP response. So you can just return the next component from the method and the Right Thing™ will happen. If you return nil, the visitor will see the current component again (though with a whole server round-trip and a fresh HTML response, so it’s best to do some AJAXey thing: on which more later!).

If you’re really interested in how the other component works, check out its source from GitHub.

But that’s not why we’re here.

Adding a component involves a boatload of boilerplate: five new files, and a change to the GNUmakefile. That’s one more boatload than you’d like to write every time you create a new page in your web app, yes?

Yes. Therefore what I actually did was to write a script to do all of that boilerplate for me. It’s really basic (error checking is for security boffins. Oh, wait.) but will do the necessary dance. Just be sure not to run it twice for the same component yet…

What I really need is a tool that’s both more robust, and that can generate the other things you need in writing a WO app. I’ll start right now, but pull requests are always welcome…

Using Objective-C on the server

My talk at NSConf was about cross-platform Objective-C. Those people who I talked to after the session will know that my goal is clear. There are plenty of people out there who have learned Objective-C to get onto the iOS or Mac app stores. Those people need some server-side smarts in their apps, and want to benefit from the skills they’ve already acquired. In other words: they want Objective-C on the server.

I’m now in a position to offer that :). I took a look at the GNUstepWeb project, a reimplementation of WebObjects 4.5. It was in a fairly parlous state, and wouldn’t even build on my Mac. I’ve fixed that. It’s still a bit of a faff, but we’re in a position to start playing with server-side ObjC and see whether there’s any value in having a better product.

Building GSW on the Mac

GNUstep-make

First, you need to grab GNUstep from SVN. Now you need to compile GNUstep-make, the build system. On Mac OS X you do the following:

cd modules/core/make
./configure --with-library-combo=apple-apple-apple
make
make install

The weird configure invocation tells GNUstep you’re going to use the Apple Objective-C runtime, and the Foundation (and AppKit) libraries instead of GNU replacements.

GNUstep-make includes a shell script that defines the locations of various folders. You should import that into your shell environment:

. /Library/GNUstep/Makefiles/GNUstep.sh

Consider adding that line to your .bash_profile.

GNUstep-base

Then you build the GNUstep-base extensions, some additional classes and macros for working with Foundation code.

cd modules/core/base
./configure
make
make install

GDL2

GDL2 is the GNUstep Database Library; an EOF-like framework for interacting with databases. If you’re going to use a DBMS like MySQL for your web apps, you should install that and its developer headers before doing:

cd modules/dev-libs/gdl2
./configure --disable-gorm-palette
make
make install

(Aside: GORM is the GNUstep version of Interface Builder. You don’t need the plugin for working with entities in GORM, and you can’t build it on Mac OS X so that’s why it’s disabled in the configure invocation.)

GNUstepWeb

Now here’s the good stuff. Build and install GSW. At time of writing, there’s an open bug that stops it building on Mac OS X, so you’ll need to grab the patch from this bug report. Apply that patch, then:

cd modules/dev-libs/gsweb
./configure
make
make install

A sample app

You probably want to see a sample GSW app, so it’s a good job I wrote one :-). Clone the HelloGSW project on GitHub. I’ll show you how to build and run that before we get into how it works.

Building HelloGSW

cd HelloGSW
make

Running HelloGSW

HelloGSW.gswa/Contents/MacOS/HelloGSW

this will spit a load of output to the console, including a URL that looks like http://localhost:9001/WebObjects/HelloGSW.woa/0/. Open that URL in your browser. You should see this:

Hello from GSW

HelloGSW code walkthrough

The interesting code is in the Main class, which is a subclass of GSWComponent (and conventionally the default component to show for a new visitor). Each “page” in a GSW app is a component, though of course you could arrange to return XML, JSON or any other format rather than HTML. HTML is the default and the easiest to work with, and indeed we’ll start by looking at a section of the HTML file, Main.wo/Main.html.

 <p>The time is <webobject name=now_string></webobject>.</p>

This is clearly the paragraph that puts the date onto the screen, but you can see that there’s this weird <webobject> tag in there. That’s going to be substituted with our date object at runtime, but how? To answer this question, look at the Main.wo/Main.wod file.

now_string:WOString {value = now}

This file contains bindings, which if you’re familiar with Cocoa work pretty similar to Cocoa Bindings. This tells us that there’s a web object called now_string, that it’s an instance of WOString, and that its value binding is bound to something called now.

That now binding is actually a key on the component object. We might expect to see a method called -(NSString *)now defined on Main to fill in the value of this string. Indeed, if we look at Main.m:

- (NSString *)now {
  NSDate *theDate = [NSDate date];
  return [theDate description];
}

Where to go from here?

The start is to build more GSW apps, and of more complexity. However there are things that need to be done along the way: all of the rest of the code and files in this project are meaningless boilerplate. This stuff needs to be hidden, automated or removed. Then we can also automate the process: compare how much of a faff setting up this app was with running a Rails app in Heroku (and I haven’t even set up an adaptor to a real web server!). It’d be really useful to simplify common tasks in modern web applications, such as exposing REST interfaces and non-HTML document formats.

Conclusions

Objective-C is not just a client app language. It’s got a long heritage as a server technology, but unfortunately the tools for doing that are quite out of date. They’re still useful though, so people who have come into the Objective-C fold recently can expand the use of their newly-found skills. Hopefully people will adopt—and contribute to—GNUstepWeb and help everyone to make it a useful modern server technology.

On home truths in iOS TDD

The first readers of Test-Driven iOS Development (currently available in Rough Cuts form on Safari Books Online: if you want to buy a paper/kindle/iBooks editions, you’ll have to wait until it enters full production in a month or so) are giving positive feedback on the book’s content, which is gratifying. Bar last minute corrections and galley proof checking, my involvement with the project is nearly over so it’s time for me to reflect on the work that has dominated my schedule for over a year.

As explained in the book’s front matter, I chose to give all of the examples in the book and accompanying source code using OCUnit. As the BBC might say, “other unit test frameworks are available”. Some of the alternative frameworks are discussed in the book, so interested readers can try them out for themselves.

What made OCUnit the correct choice—put it a different way, what made OCUnit the choice I made? It’s the framework that’s shipped with Xcode, so anyone who might want to try out unit testing can pick up the book and give it a go. There are no third-party dependencies to become unsupported or change beyond all recognition—though that does occasionally happen to Xcode. File-New Project…, include unit tests, and you’re away, following the examples and trying out your own things.

Additionally, the shared body of knowledge in the Cocoa development community is greatest when it comes to OCUnit. Aside from people who consider automated testing to be teh suck, plenty of developers on Mac, iOS and other platforms have got experience using OCUnit or something very much like it. Some of those people have switched to other frameworks, but plenty are using OCUnit. There’s plenty of experience out there, and plenty of help available.

The flip side to this is that OCUnit doesn’t represent the state of the art in testing. Far from it: the kit was first introduced in 1998, and hasn’t changed a great deal since. Indeed many of the alternatives we see in frameworks like GHUnit and Google Toolkit for Mac are really not such great improvements, adding some extra macros and different reporting tools. Supporting libraries such as OCHamcrest and OCMock give us some additional features, but we can look over the fence into the neighbouring fields of Java, ruby and C# to see greater innovations and more efficient testers.

Before you decide to take the book out of your Amazon basket, let me assure you that learning TDD via OCUnit is not wasted effort. The discipline of red-green-refactor, the way that writing tests guides the design of your classes, the introduction of test doubles to remove dependencies in tests: these are all things that (I hope) the book can teach you, and that you can employ whether you use OCUnit or some other framework. And, as I said, there’s plenty of code out there that is in an OCUnit harness. It’s not bad, it could be better.

So what are the problems with OCUnit?

  • repetition. Every time you write STAssert, you’re saying two things. Firstly, “hey, I’m using OCUnit”, which isn’t really useful information. Second, “what’s coming up is a test, read on to find out what kind of test”. Then you finally get to the end of the macro where you reveal what it is you’re going to do. This is the important information, but we bury it in the middle of the line behind some boilerplate.

    Imagine, instead, a hypothetical language where we could send messages to arbitrary expressions (ok that exists, but imagine it’s objc). Then you could do [[2+2 should] equal: 4]; which more closely reflects our intention.

  • repetition. In the same way that STAssert is boilerplate, so is sub classing SenTestCase and writing -(void)test at the beginning of every test method. It gives you no useful information, and hides the actual data about the test behind the boilerplate.

    Newer test frameworks in languages like C# and Java use the annotation features of those languages to take the fact that a method is a test out of its signature and make it metadata. ObjC doesn’t support annotations, so we can’t do that. But take a look at the way CATCH tests are marked up. You indicate that something is a test, and the fact that this means the framework needs to generate an objective-c++ class and call a method on it is encapsulated in the framework’s implementation.

  • repetition. You might think that there’s a theme developing here :-). If you write descriptive method names, you might have a test named something like -testTheNetworkConnectionIsCleanedUpWhenADownloadFails. Should that test fail, you’re told what is going wrong: the network connection is not cleaned up when a download fails.

    So what should you write in the mandatory message parameter all of the STAssert…() macros require? How about @"the network connection was not cleaned up when a download failed"? Not so useful.

  • organisation. I’ve already discussed how OCUnit makes you put tests into particular classes and name them in particular ways. What if you don’t want to do that? What if you want to define multiple groups of related tests in the same class, in the way BDD practitioners do to indicate they’re all part of the same story? What if you want to group some of the tests in one of those groups? You can’t do that.

I’m sure other people have other complaints about OCUnit, and that yet other people can find no fault with it. In this post I wanted to draw attention to the fact that there’s more than one way to crack a nut, and the vendor-supplied nutcracker is useful though basic.

So you don’t like your IDE

There are many different tools for writing Objective-C code, though of course many people never stray much beyond the default that’s provided by their OS vendor. Here are some of the alternatives I’ve used: this isn’t an in-depth review of any tool, but if you’re looking for different ways to write your code, these are tools to check out. If you know of more, please add to the comments.

In most cases, if you’re writing Mac or iOS apps, you’ll need the Xcode tools package installed anyway in order to provide the SDK frameworks (the libraries and headers you’ll be linking against). The tools basically provide a different user interface to the same development experience.

A word on IDEs. The writers of IDEs have an uphill struggle, in that every user of an IDE assumes that they are a power user, though in fact there are a wide range of abilities and uses to which IDEs are bent. My experience with Eclipse, for example, ranges from learning Fortran 77 to developing a different IDE, in Java and Jython, using the same app. Visual Studio is used to write single screen line-of-business apps in Visual BASIC, and Windows. Different strokes for different folks, and yet most IDEs attempt to accommodate all of these developers.

CodeRunner

CodeRunner is not a full IDE, rather it’s a tool for testing out bits of code. You get a syntax-highlighting, auto completing editor that supports a few different languages, and the ability to quickly type some code in and hit “Run”. Much simpler than setting up a test project in an IDE, and only a handful of denarii from the App Store.

CodeRunner.app

AppCode

AppCode is the engine from well-respected IDE IntelliJ IDEA, with Objective-C language support. Its language support is actually very good, with better (i.e. more likely to work) refactoring capabilities than Xcode, useful templates for creating new classes that conform to protocols with default implementations of required methods, and quick (and useful!) navigation categories.

AppCode uses Xcode project files and workspaces, and uses xcodebuild as its build system so it’s completely compatible with Xcode. It doesn’t support XIBs, and just launches Xcode when you try to edit those files.

It’s also important to notice that AppCode is currently available under an “early access” program, with expiring licences that force upgrade to newer builds. There’s no indication of when AppCode will actually be released, and what it will cost when it gets there. For comparison, the community edition of IDEA is free while the “Ultimate” edition costs anything up to £367, depending on circumstances.

AppCode.app

Emacs

Emacs’s Objective-C mode is pretty good, and it can use ctags to build a cross-file symbol table to provide jumping to definition like a “real” IDE. In fact, it would be fair to say that emacs is a real IDE: you can interact with version control directly, do builds (by default this uses Make, though you can easily tell it to run xcodebuild instead), run your app through gdb and other goodies.

That said, I think it’s fair to say that emacs is only a powerful tool in the hands of those who are comfortable with Emacs. It’s only because I’ve been using it forever (I actually started with MicroEmacs on AmigaOS, and wrote LISP modes in my Uni days) that I even consider it an option. It’s nothing like an app on any other system: Cocoa’s field editor supports a subset of emacs shortcuts but otherwise emacs feels nothing like a Mac, UNIX, Windows or anything else app. (Before the snarky comments come in, vim is just as odd.)

Emacs.app

Conclusion

There are more ways out there to write your Objective-C code than just Xcode. These are a few of them: find one that works well for you.