Objective-C

There are 38 entries in this Category.

Mapping Strings to Selectors

MappingStringsToSelectorsSketchBack in the old days of Carbon, when you wanted to handle a button press, you set up a command ID on your button, which was a simple integer, and then implemented a central command-handling function on your window that received the command ID and used a big switch statement to dispatch it to the right action.

In Cocoa, thanks to message sending and target/action, we don’t have this issue anymore. Each button knows the message to send and the object to send it to, and just triggers the action directly. No gigantic switch statement.

However, we still have a similar issue in key-value observing: When you call addObserver:forKeyPath:options:context, all key-value-observing notifications go through the one bottleneck: observeValueForKeyPath:ofObject:change:context:. So, to detect which property was changed, you have to chain several if statements together and check whether the key path is the one you registered for (and check the ‘context’ parameter so you’re sure this is not just a KVO notification your superclass or subclass requested), and then dispatch it to a method that actually reacts to it.

It would be much nicer if Apple just called a method that already contained the name of the key-value-path, wouldn’t it? E.g. if the key-path you are observing is passwordField.text, why doesn’t it call observerValueOfPasswordField_TextOfObject:change:context:?

But there is a common Cocoa coding pattern that can help us with this: Mapping strings to selectors. The centerpiece of this method is the NSSelectorFromString function. So imagine you just implemented observeValueForKeyPath:ofObject:change:context: like this:

-(void) observeValueForKeyPath: (NSString*)keyPath ofObject: (id)observedObject change: (NSDictionary*)changeInfo context: (void*)context
{
    NSString *sanitizedKeyPath = [keyPath stringByReplacingOccurrencesOfString: @"." withString: @"_"];
    NSString *selName = [NSString stringWithFormat: @"observeValueOf%@OfObject:change:context:", sanitizedKeyPath];
    SEL      action = NSSelectorFromString(selName);
    if( [self respondsToSelector: action] )
    {
        NSInvocation * inv = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector: action]];
        [inv setTarget: self]; // Argument 0
        [inv setSelector: action]; // Argument 1
        [inv setArgument: &observedObject atIndex: 2];
        [inv setArgument: &changeInfo atIndex: 3];
        [inv setArgument: &context atIndex: 4];
        [inv invoke]
    }
    else
        [super observeValueForKeyPath: keyPath ofObject: observedObject change: changeInfo context: context];
}

We build a string that includes the name of the key-path, turn it into an actual selector, and then use -performSelector:withObject:, or in more complex cases like this one NSInvocation, to actually call it on ourselves.

For cases that have no clear mapping like this, you can always maintain an NSMutableDictionary where the key is whatever string your input is and the value the selector name for your output, and then use that to translate between the two. When you make whatever call equivalent to addObserver: you have in that case, it would add an entry to the dictionary. That’s probably how NSNotificationCenter does it internally.

Update:
As Peter Hosey pointed out, another good use case for this pattern is -validateMenuItem: where one could turn the menu item’s action into a string and concatenate that with ‘validate’.

Blocks and block lists

doctor_who_blocks

When I first heard about blocks, I was horrified. All the un-clean code structure of huge ten-page functions, plus the loss of self-documenting function names. Why would someone want anonymous functions? And even worse, anonymous functions that can cause retain circles because they automatically retain objects you reference, because they have access to the scope of the surrounding function, like nested functions?

Then, at one NSConference, someone pointed out that they are really good for making asynchronous code look more synchronous. Who would have thought that blocks, carefully used, could actually improve readability of code?

Imagine you are using an NSURLConnection to retrieve a JSON file from a server and extract information from it. In synchronous pseudocode:

-(void) showInfo
{
    NSString* myJSON = [NSString stringWithContentsOfURL: @"http://example.com/data.json"];
    if( myJSON == nil )
    {
        [self reportError];
        return;
    }
    NSString* userText = [self prettyPrintJSON: myJSON];
    [self showPanelWithText: userText button: @"OK"];
}

Minimal code for doing this asynchronously and avoid blocking the user interface and spinning the beach ball when the connection is slow includes creating an NSURLConnection, setting yourself as its delegate then displaying any error you get from one delegate method, or when the request completes and a second is called, to actually process the request. So the above code turns into pseudocode:

-(void) showInfo
{
    self.connection = [[NSURLConnection alloc] initWithURL: @"http://example.com/data.json"];
    myConnection.delegate = self;
    [myConnection start];
}

-(void) connection: (NSURLConnection*)sender didFinishLoading: (NSString*)myJSON
{
    NSString* userText = [self prettyPrintJSON: myJSON];
    [self showPanelWithText: userText button: @"OK"];
    self.connection = nil;
}

-(void) connectionDidFailLoading: (NSURLConnection*)sender
{
    [self reportError];    
}

Notice how 5 straightforward lines have turned into a spaghetti of three methods? Now imagine you had to chain several requests. You’d have to create separate delegate objects for each request, or key off the ‘sender’ parameter and handle the OK case for all requests together in one delegate method, and the error cases together in another.

Now how does that look with blocks (still pseudocode)?

-(void) showInfo
{
    [NSURLConnection sendAsynchronousRequest: @"http://example.com/data.json" completionHandler: ^( NSURLRequest req, NSString* myJSON, NSError* error )
        {
            if( error )
            {
                [self reportError];
                return;
            }
            NSString * userText = [self prettyPrintJSON: myJSON];
            [self showPanelWithText: userText button: @"OK"];
        }];
}

Shockingly, that almost looks like our original, synchronous code. Now to be fair, if someone at Apple had added a delegate method to NSURLConnection that combined the error case and the success case like the above block does, the original example would be a tad simpler as well. But performing several requests in sequence would still split the actual requests from their replies, and group them by request or reply.

With blocks, on the other hand, two requests in sequence would look almost like the synchronous code would, with nested ifs:

-(void) showInfo
{
    [NSURLConnection sendAsynchronousRequest: @"http://example.com/data.json" completionHandler: ^( NSURLRequest* req, NSString* myJSON, NSError* error )
    {
        if( error != nil )
        {
            [self reportError];
            return;
        }

        NSString* userText = [self prettyPrintJSON: myJSON];
        [self showPanelWithText: userText button: @"OK"];

        [NSURLConnection sendAsynchronousRequest: @"http"//example.com/data2.json" completionHandler: ^( NSURLRequest* req2, NSString* myJSON2, NSError* error2 )
        {
            if( error2 != nil )
            {
                [self reportError];
                return;
            }

            NSString * userText2 = [self prettyPrintJSON: myJSON2];
            [self showPanelWithText: userText2 button: @"Done"];
        }];
    }];
}

You’re probably already seeing where our problem is, though. Since every block adds one level of brackets and depth, it becomes pretty hard to re-order requests. You’d have to cut the inner request out, then wrap it around the outer request so it only triggers the other request on success.

But here is where it comes in handy that blocks aren’t just nested functions. Blocks are actually real Objective-C objects. So, we can keep an array of blocks:

-(void) showInfo
{
    NSMutableArray * steps = [NSMutableArray array];
    [steps addObject: ^( NSMutableArray * steps )
    {
        // First request start:
        [NSURLConnection sendAsynchronousRequest: @"http://example.com/data.json" completionHandler: ^( NSURLRequest* req, NSString* myJSON, NSError* error )
        {
            if( error != nil )
            {
                [self reportError];
                return;
            }

            NSString* userText = [self prettyPrintJSON: myJSON];
            [self showPanelWithText: userText button: @"OK"];
            // First request end.

            [[steps[0] retain] autorelease]; // Make sure we don't go away.
            [steps removeObjectAtIndex: 0];
            steps[0]( steps );
        }];
    }];
    [steps addObject: ^( NSMutableArray * steps )
    {
        // Second request start:
        [NSURLConnection sendAsynchronousRequest: @"http://example.com/data2.json" completionHandler: ^( NSURLRequest* req2, NSString* myJSON2, NSError* error2 )
        {
            if( error2 != nil )
            {
                [self reportError];
                return;
            }

            NSString* userText2 = [self prettyPrintJSON: myJSON2];
            [self showPanelWithText: userText2 button: @"OK"];
            // First request end.

            [[steps[0] retain] autorelease]; // Make sure we don't go away.
            [steps removeObjectAtIndex: 0];
            steps[0]( steps );
        }];
    }];
    [steps addObject: ^( NSMutableArray * steps )
    {
        // Done.
    }];
    steps[0]( steps ); // Kick off execution
}

So, we add the blocks to an array with 3 -addObject: calls, then at the bottom run the first block in the array. When each block is done, it removes itself from the array, and runs the next block in the array (except for the last block, which is simply there so the second-to-last block has someone after it to call — we could also just check whether the array is empty before trying to call the next block). This looks a little more complicated than it should, but if wrapped in an ObjC class with a -next method is very readable.

Now, if you want to re-order two requests, you simply re-order the -addObject: calls. Since none of the blocks care which block follows them, you don’t need to wrap anything around anything else.

You can now read all requests in sequence (hence I call these things block sequences), ignoring the spots at which control is given up to the system for a while, and re-arrange them as you please. Neat, huh?

Why Cocoa programmers can’t have nice things

IMG_0315
Amy Worrall pointed me at a nice post on the technical feasibility of using exceptions for more than programming errors in Cocoa by Hari Karam Singh. Even though he is misled by some Mac documentation into thinking iOS didn’t have zero-cost exceptions and then disproves that documentation by disassembly, he draws lots of valid conclusions.

However, the problem is not one of technology. The problem is one of the sheer size of Apple’s Cocoa codebase, which would have to be updated to survive having an exception thrown through it. Apple would have to add @trys in every location where they call a SEL, after all, since they don’t know which of them may be user-provided and throw.

Since they’re not doing that, a user who decides to use exceptions anyway would have to add @trys to every method that might ever be called by the framework. That means you can’t catch exceptions thrown by that method when you call it, though, because it swallows them itself. So if you want to handle errors from that method, you either split it up into okButtonClickedThrows: and okButtonClicked:, duplicating every method and working in parallel with two error handling schemes, or you give up, like Apple, and just use one non-exception error handling scheme.

I love exceptions, but I don’t think my Cocoa code will be cleaner and error handling nicer if I put a try block at the top of every action and delegate method. NSError is less dangerous, because if an object returns nil and gives an error (and you don’t look at the returned error), the method call will simply collapse (call to NIL is a no-op) so nothing much will happen. Since I can’t put up an error dialog from drawing code or table delegate callbacks like numberOfSections, there’s not much difference there. The code is actually cleaner, because with NSError and nil returns I can just ignore errors, while with exceptions in an exception-unsafe Cocoa, I must catch here or I’ll risk throwing through Cocoa.

C++ also has an advantage when working with exceptions over Objective-C because it uses “Resource Acquisition Is Initialization” (or RAII for short). Locks, allocations, even changes of a global boolean can be implemented as stack objects using RAII to set themselves up when created and clean up behind themselves in their destructor. You don’t even have a ‘finally’ block in the language. OTOH, every method you write in an exception-handling ObjC would need an @finally block, even if it doesn’t care about the errors, just to clean up behind itself.

ARC, @autoreleasepool and @synchronized can help a little with clean-up of memory and locks these days, as they’ll get triggered on an exception anyway. But as Cocoa and Apple’s frameworks currently stand, using exceptions effectively doubles your work.

The same applies to existing code. Nobody wants to have to completely rewrite their apps for 10.9 just to adopt a new error handling scheme when their code already has working error handling with NSError. Apple understands that their developers want a certain degree of backward compatibility. That’s the reason why only iOS got the new runtime on 32-bit: There was no code that relied on the old runtime there, it was a new platform. But all existing Mac applications would have been broken if the system had suddenly no longer guaranteed instance variable layouts and method lookup-tables. However, since 64-bit required changes to pointer sizes and data structures anyway, nobody complained when Apple introduced the new runtime for 64 bit on the Mac. They had to re-test and update their applications anyway.

All that said, I would love a new Objective-C framework that uses exceptions and is exception-safe for new projects to be built against. It just doesn’t seem like something Apple can retrofit at a whim.

At best, they can slowly make each framework exception-safe, and then in every spot where there can be an error, instead of returning it, look at an “app supports exception handling”-flag and throw their errors if that is set. That way, existing applications will keep working, while new applications can be written exception-safe. And once the majority of applications have moved to exceptions, Apple can switch to using exceptions themselves (see above — you don’t want 2 versions, exception-safe and unsafe, of every method), and tell the stragglers to please make their code exception-safe.

Setting up Jenkins for Github and Xcode, with Nightlies

IMG_0320

Jenkins? What? Why?

When you work alone on a several projects that share code, it’s easy to unnoticeably break the build of one project with a change for the other, or introduce some specific dependency on a quirk of your main work Mac, or lose data by referencing a file outside the repository instead of copying it in. Since that’s annoying, I decided to set up Jenkins, a continuous integration system, on my Mac mini that serves as my EyeTV DVR, media centre and home server.

It’s not that hard, but some of the details are a bit fiddly and under-documented, so I thought I’d write down how I made it work before I forget it (and for when I next have to set it up again). My source code is in a Github repository, and while I was at it, I wanted to set it up that one of my open source projects gets nightly builds FTPed onto its web site (but only when I’ve actually changed something).

Initial Install

Jenkins is a Java application. Since Java no longer comes pre-installed on Mac OS X, if you’re not using any other Java applications, you should open a Terminal and type in java, which will make Mac OS X notice Java is not yet installed and download it. Also make sure you’ve installed Xcode on your Mac. The version from the app store is fine, but make sure you install the command line tools under Preferences > Downloads on the Components tab, so Jenkins will be able to find git.

Next, you’ll want to create a dedicated user account that Jenkins will run under. The standard installer does that for you, but it only creates a command-line account, which makes it very hard to set up all the certificates, so go to System Preferences‘s Users & Groups section, and create a new account and name it “Jenkins”. Make sure you enter “Jenkins” with a capital ‘J’ under “Account name”. Also, right-click the account in the list on the left and choose “Advanced Options…”. Replace the standard home directory “/Users/Jenkins” with “/Users/Shared/Jenkins”, which is what the standard installer will use. Update: Getting reports that this is broken in 10.9.2 (or maybe a new Jenkins installer released around that time). So I guess you’ll have to set up everything using the command line.

Now that all is ready, go to jenkins-ci.org, and right on the front page you’ll find a Mac OS X direct download link that gives you a nice Mac installer package. Run that. Jenkins will be installed so it automatically launches at system startup, and it will run on your Mac on Port 8080. So make a note to later forward that port through your router to your Mac so it is accessible from the outside (you will need a dynDNS domain-name connected to it, or a static IP, or Github won’t be able to notify you of changes). But not yet! First you have to secure Jenkins with a password.

Open your browser and point it at http://localhost:8080 (your Mac’s Bonjour name is fine as well, as will be your external domain name or IP, when you later set up the port forward). And after a short wait you’ll get to Jenkins’ front page. There’s a breadcrumb bar at the top which pops up a little menu if you mouse over the initial Jenkins breadcrumb:

Jenkins front page

Under Manage Jenkins, click Configure Global Security and there, check Enable Security, but do not save yet! If you do, Jenkins will happily lock you out. You haven’t created a user login yet, so you’ll never be able to get back in again without editing the config.xml in the Jenkins user folder and manually deleting the three security-related lines in there.

Next, we’ll have to set up permissions for the new user login, and then actually create it. So first tell Jenkins to use Jenkins’s own user database and Allow users to sign up under Security Realm. Then check Matrix-based security and type whatever user name you want into the little User/group to add: field and click Add. Then make sure that all checkboxes are checked for this user login, all the way to the right, and all are off for “Anonymous”.

Screen Shot 2013 04 06 at 00 20 36

Now that that’s done, you can save. Then click Sign up in the upper right and sign up under the user name you just gave all the permissions to. Yay! We have a valid user! Now go and turn off the Allow users to sign up checkbox again so nobody else makes themselves an account on your server.

Git support

By default, Jenkins only does SVN. But it has a nice big list of plug-ins that you can easily install. Go to the menu, Manage Jenkins > Manage Plugins and go on the Available tab. There’s a boatload of plugins there, but we only care about one for now: Github Plugin. Find it (there are a few with similar names) and install it. Check the box to restart after the installation.

If you’re curious about a plugin, just click its name. It will show a web site with documentation and setup instructions. Installing a plugin means that its checkboxes and text boxes show up in the Configure System section and each job’s Configure section. So let’s go to Configure System.

Take note of the Home directory mentioned at the top. This is where you’ll later be installing your Github certificates so Jenkins can check out code. Also, since you want your Jenkins externally accessible, scroll down to Jenkins Location and enter your external URL or static IP as the Jenkins URL there.

Between those two is a Git category. Click the lone Git installations… button there. If you installed the Xcode command line tools as mentioned, you will not see a red error message here and it will have found git in the default location. Otherwise, set up the search paths to point wherever you have git installed.

Now go to Github Web Hook and check Let Jenkins auto-manage hook URLs and enter your username and password in the fields that show up. This is needed so Jenkins can install a script that notifies it whenever a new commit has been pushed, so it’ll start a build. Click Test Credential to make sure that works.

GithubWebHook

Setting up a job

In Jenkins, everything that is built periodically is represented as a Job. To create a new job, click New Job in the upper left on the Jenkins home page. In the page that follows, choose a name (but be sure not to use spaces, as this name will be used for the folder in which Jenkins will work, and you’ll have much less trouble with a shell-script-friendly name), and select “Build a free-style software project”.

Jenkins New Job Page

Click OK, and you’ll get to that job’s Configure page. Select Git under Source Code Management and enter the URL you see on Github under SSH for your repository twice, once in Github project at the top, and as the Repository URL under Source Code Management:

Creating a new Jenkins Job

And finally, check Build when a change is pushed to Github under Build Triggers:

Screen Shot 2013 04 06 at 13 44 07

Now you’ve set up Jenkins so it will try to check out your code whenever a change happens. Next, we will have to tell it how to actually build it. We do that in the Build section. Click Add build step and choose Execute shell. You’ll get a text field in which you can enter a shell script.

This shell script will be run in the folder into which your repository was checked out. This will be a folder named after your job in the workspace subfolder of your jenkins user’s home directory. So if your Xcode project file is at the root of the repository, you can just call xcodebuild there. If it’s in a subfolder, you can cd SubFolderName and then call xcodebuild.

Set up a Jenkins build

One problem with Xcode is that it builds into a hardly-predictable folder somewhere in Library. Jenkins requires all built files to be inside a job’s workspace folder, or it won’t let you archive them. So we need to override it to e.g. build into a build folder inside the checkout. To achieve this, we set the CONFIGURATION_BUILD_DIR environment variable when we call xcodebuild. Note the example screenshot hard-codes the path, while I now use one of Jenkins’ environment variables:

BUILD_DEST_PATH=${WORKSPACE}/build

The script above, once it is done, grabs the files from the build folder and compresses them into a single archive. This is so we can archive the built file somewhere, for future reference. The actual archiving is done under Post-build Actions where we select Archive the artifacts from the Add post-build action popup. Here again, the path is relative to your job’s workspace subfolder, so if you want to archive something added to the build folder, use a relative path like build/MySweetApp.tgz.

Note that Jenkins tries to be helpful and displays red warnings that it can’t find the file to archive right now. At this point, that’s OK. There is no checkout, and we’ve never archived anything. However, later, this can be very helpful in figuring out what’s gone wrong, if the checkout works, but building fails or so.

Done? Then save. You could also click Build Now on the left (or the little clock with the green “run” arrow on it anywhere next to your newly-created job on the home page), but it would fail. Apart from errors in your script, there would likely be two issues, which you can see in the menu that shows up when you hover the mouse over any failed build and click “Console Output” in the menu that shows up:

  1. Github will complain that you don’t have permission/are missing certificates
  2. Xcode will complain you haven’t accepted its license agreement.

Remember when you set up access to Github for the first time and you had to create and install certificates? You’ll have to do that for your Jenkins user, too. Or you could simply copy the hidden .ssh folder in your user directory over into the Jenkins user’s home folder. Note that this isn’t e.g. /Users/Shared/Jenkins/Home like in the standard installation, but actually one folder up, so you want your certificates in /Users/Shared/Jenkins/.ssh/.

Note you’ll have to

sudo cp -R ~/.ssh /Users/Shared/Jenkins/
sudo chown -R jenkins /Users/Shared/Jenkins/.ssh

to make the folder accessible to the Jenkins user. If you created a real GUI-user for jenkins, you can simply run Xcode once and accept the license agreement once. Alternately, as the error message from xcodebuild will tell you, you can do

sudo -u jenkins -i
xcodebuild -license
exit

To view the license. While you’re in the license screen, you can skip to the end by typing an uppercase G (you’ve already accepted the license agreement when installing the command line tools from inside Xcode, after all), then type in agree, as directed.

If you now click Build Now on Jenkins’s home page, it should work. The job should show up in the Build Queue, the ball at its left should flash for a while, and the similar ball next to the job in the list of jobs on the home page should be blue. If it is red, click the Job’s name, and in the Build History on the left mouse over it and choose Console Output to see the log and error messages.

If a build was successful, you can view the archived files (“artifacts”) by clicking a job on the home page, and then one of the individual build times listed at the bottom of its page.

Setting up nightly builds

If you want to make nightly builds and not just have them in Jenkins, but actually upload them to an FTP server somewhere, you will need the FTP Publisher Plugin. Install it, then go into Manage Jenkins > Configure System and scroll to the new FTP repository hosts section. You can create a preset for each server you have. Since Jenkins is publicly accessible, I recommend creating a separate user for Jenkins and restricting it to only a nightlies folder on the server, and no CGIs. That way, should Jenkins somehow be hacked, people at least can’t use the password and login to deface the rest of your server (even though they *can* replace the downloads).

FTP Server settings

Once you’ve added your server, create a new job (e.g. MySweetAppNightly, but this time check Copy existing Job and type in the name of your regular CI job as the template (e.g. MySweetAppCI). Then just add a new action to Post-build Actions, by choosing Publish artifacts to FTP from the Add post-build action popup. Select your server from the FTP site popup and write the relative path name of the TGZ archive you set up in Files to upload (in our example, that would have been build/MySweetApp.tgz). Leave the Destination-field empty, unless you want to upload into a subfolder of the folder you set up in System Configuration. If you are building into a subfolder (like in our example build/MySweetApp.tgz), you may also want to check Flatten files, or it will upload into a subfolder of the same name on the server.

Now, what this would do right now is upload every change to the FTP server. The server would be strained unnecessarily if your application contains large assets. We want a nightly build. How do we do this? We scroll up to Build Triggers, turn off Build when a change is pushed on Github, and check Poll SCM. Now, we could just pick Build periodically, which is almost identical, but the advantage of Poll SCM is that it won’t build and upload if nothing has changed since the last build. (It would also be the right option if you host somewhere else than Github and can’t use the plugin and don’t want to write your own post-commit hook.

Click the question mark next to the Schedule text field to see the syntax, it is pretty much like cron. I picked 4 AM at night, every day of the week. That’s a time where I’m usually not in the middle of a series of check-ins, so chances are this should build.

Jenkins Build Triggers for Nightlies

If you hardcoded the path in the Build section, be sure to rename the job in the path there, then save and click Build Now to generate and upload your first nightly build.

Getting notified

Of course, all of this would be pretty pointless if we had to check Jenkins after every commit. Luckily, Jenkins can e-mail you. You need an e-mail account somewhere (I recommend creating one dedicated to Jenkins, again for security reasons, but any old Hotmail account would work). Scroll to “E-Mail Notifications” in Configure System and click the Advanced button, check Use SMTP Authentication, then enter the same user name, password and SMTP server you would specify to use this account from Mail.app or another e-mail client. Check Use SSL if your mail hoster supports that.

Advanced E-Mail Notifications

Then check Test configuration by sending test e-mail and enter whatever e-mail addres you want to send a test e-mail to in Test e-mail recipient and click Test configuration. If you mis-configured something, you’ll get Java throwing up backtraces in red all over your window. Enjoy.

Now, all that’s left is adding a E-mail Notification Post-build action to each job. Happy continuous integration, and a happy new year.

I also installed the Twitter plugin and added that as a Post-build action to notify me whether the build is broken. It is pointed at a protected Twitter account that only I can follow. You have to run a little Java command-line app to get the API access tokens needed for Jenkins to talk to Twitter, and paste those into text fields on Jenkins’ System Configuration, but that’s as complicated as it gets.

Certificates and DeveloperID Builds

If you want to build your Mac executables for distribution outside the Mac app store, you will need to log into your Jenkins user and open Xcode, and there go into the Organizer. Click Refresh in the Provisioning Profiles section (click OK in any App Store certificates not existing error messages it may put up if you only want to go outside the MAS, or you work Mac-only and not iOS).

Next, click your team. If it says there are no private certificates across the top, go to a Mac that has all your certificates already set up for development, and in the Organizer choose Editor > Developer Profile > Export Developer Profile… to export your private keys as a password-protected .developerprofile file. Copy that file over to the Jenkins user and double-click it there, and Xcode will ask for the password and install your certificates.

Now, verify that everything works: Open the project you want to build for developer ID. Go into the project‘s build settings and set the Code Signing setting to your Developer ID Application certificate. Build the project, clicking Always allow if Xcode asks for permission to use your private key to sign the application. If the build fails with an error like “timestamps differ by 205 seconds — check your system clock Command /usr/bin/codesign failed with exit code 1”, you probably dawdled too long in the confirmation dialog. Just build again and it should work.

If codesign fails trying to sign a file that doesn’t exist, you probably have a target that doesn’t produce a file, like a target that runs a shell script to generate a header containing the build number. Since we’re overriding the code signing setting for the entire project, it will try to sign that nonexistent output file. One way to satisfy it is to add a line like touch ${CODESIGNING_FOLDER_PATH} to the end of your script, which will create an empty file for codesign to sign.

Now that we know you have code signing set up correctly, we simply modify the call to xcodebuild in the job you want to have signed for Developer ID:

security unlock-keychain -p 's3kr1tp4ssw0rd' ~/Library/Keychains/login.keychain
xcodebuild CONFIGURATION_BUILD_DIR=$BUILD_DEST_PATH  \
  CODE_SIGN_IDENTITY="Developer ID Application: Joe Shmoe" \
  -configuration Release \
  clean build

The first call to security unlock-keychain does just that: Give xcodebuild running under Jenkins access to the keychain containing the keys it needs for code signing. Here you need to specify the keychain’s password, which is not a very secure thing to do, but can’t really be avoided in this case. At some point, the server *will* need access to your keys to build.

For a tiny bit of extra peace of mind, you might want to change the password of your keychain to be different from the account’s login password using the Keychain Access application. That way, if someone somehow manages to see this script and the password to the keychain, they still can’t log into your build tester to actually use it.

Alternately, you could run the Jenkins server that is exposed to the outside and manages the job on a different Mac (or at least as a different user?) than the actual build server. Jenkins allows that, so you can e.g. have one Jenkins web interface to build Mac, Windows and Unix software.

The second call is the same as our previous xcodebuild call, with three parameters added:

  1. The first one does in script what we did manually for testing in the GUI: It overrides the “Code Signing:” build setting with the Developer ID certificate (Insert your name here).
  2. The second one makes sure we don’t build with whatever configuration was last set, but instead make a release build, with optimizations and such. You could also specify that for other cases, if you wanted, to make sure e.g. stuff you remove from release builds doesn’t break the debug builds or vice versa.
  3. The third makes sure we clean before we build. This makes sure you don’t get any leftover files from a previous build (e.g. script-generated header files), but is also slower than an incremental build. You would probably also want to do this for nightly builds, but probably not for a CI build that gets triggered a lot, unless your project is very small.

Including the job number

For my nightly builds, I wanted to have a monotonically increasing version number. To add this is fairly easy: Just pass a few more settings overrides to xcodebuild:

  GCC_PREPROCESSOR_DEFINITIONS="BUILD_NUM=${BUILD_NUMBER} BUILD_MEANS=nightly" \
  INFOPLIST_PREPROCESSOR_DEFINITIONS="BUILD_NUM=${BUILD_NUMBER} BUILD_MEANS=nightly" \

The first line includes the build number that Jenkins uses for this job as a #defined constant accessible to your source files. The second does the same for projects that you have set to preprocess their Info.plist file (e.g. to include the build number in the CFBundleVersionString). You can also define other constants, separated by spaces, like BUILD_MEANS in this example, to e.g. somewhere display that this is a nightly build. You can provide default values for manual builds in a header that you include in those source files that need them, or in a prefix header for your Info.plist:

#ifndef BUILD_NUM
#define BUILD_NUM     0
#endif
#ifndef BUILD_MEANS
#define BUILD_MEANS   manual
#endif

And this should cover everything you typically need to do on your new continuous integration Mac.

Common Cocoa Coding Patterns: NSError returns

A sad iMac

Error reporting wasn’t something Cocoa did in much detail in the early days. There were nil return values instead of objects, or a BOOL that was YES on success.

C didn’t have exceptions, and by the time ObjC got “fake” exceptions based on the longjmp() mechanism, all wrapped up nicely in NSException and NS_DURING/NS_HANDLER/NS_ENDHANDLER macros, most of the framework API had already been written and it would have been too much work to make all of it work with exceptions and adapt all applications to watch for exceptions in error situations. So they were reserved mostly for Distributed Objects (where an additional error return wasn’t possible) and programming errors.

But with the release of Safari and WebKit in 2003, someone at Apple realized they needed more detailed and standardized error information, and introduced the NSError class. NSError is a simple container object for any error code you might encounter on your Apple device, plus a dictionary for any other info like an error message.

Error codes are not unique across all the libraries, frameworks and system services that are on your device, so each error code is also identified by its domain, an arbitrary string constant. For example, Mac OS X offers the NSCocoaErrorDomain, NSOSStatusErrorDomain, NSPOSIXErrorDomain and NSMachErrorDomain error domains, which let you wrap Cocoa framework error codes, Carbon/CoreServices error codes, standard Unix error codes and kernel errors unambiguously, all by wrapping them in an NSError. And you can make up your own for your application, library, and even for a single class. Whatever logical unit of encapsulation makes the most sense.

Most NSErrors are returned as a return parameter. This has the advantage that methods that already have a return value can still be implemented as they were before the arrival of NSError, and can return nil to have an entire chained expression collapse. E.g., a fictional

NSError    theErr = nil;
ULIObject  obj = [[[ULIObject allocGivingError: &theErr] initGivingError: &theErr] autoreleaseGivingError: &theErr];

can fail at any of the three calls and return nil, and none of the subsequent messages will be sent, nor will they touch theErr.

However, one thing Apple tells us is that we shouldn’t look at theErr above unless obj is nil. Why is that? Well, imagine a possible implementation of our fictional autoreleaseGivingError::

-(id) autoreleaseGivingError: (NSError**)outError
{
    ULIAutoreleasePool* currentPool = [ULIAutoreleasePool _currentPoolGivingError: outError];
    if( currentPool == nil )
        currentPool = [NSAutoreleasePool _createBottomPool];
    if( currentPool == nil )    // Still couldn't create?
    {
        // Hand on whatever error _currentPoolGivingError: had.
        return nil;
    }
    
    [currentPool addObject: self];
    return self;
}

Our fictional internal _currentPoolGivingError: method here might return nil and give us an NSError when there is no pool in place yet.

But in the most common case, we will be able to recover from this error by creating the pool 1.

So in most cases, we’ll just create the pool and add the object to it. If callers look at theErr in such a situation, they will see the error object put there by _currentPoolGivingError:, from which we recovered. So they will see an error where none occurred.

And that, kids, is why you always check the return value, and not just the error parameter.

1) This is nonsense in real life, because nobody would ever release this bottom pool and we’d have a quiet leak, but let’s just assume in our example’s world ULIRunLoop will release this bottom pool once it regains control, as part of a lazy-allocation-of-pools scheme.

View-based NSTableViews: Row 1 should be in the valid visible section

With Mac OS X 10.7 “Lion”, Apple added a second “content mode” to NSTableView: View-based table views. This allows you to simply create your list items as separate views that get reused and reshuffled to simulate scrolling, instead of using the classic approach of “rubber stamping” a more lightweight NSCell repeatedly into the window. If you’ve programmed for iOS before, this is essentially like UITableView works, just for the Mac.

While this works fairly well most of the time, as of this writing it has one severe bug: Occasionally, a view-based NSTableView‘s view hierarchy gets corrupted in some odd way, causing it to hit an assertion and throw an exception. The main message you see in that case is:

Row 1 should be in the valid visible section.

I don’t know what exactly happens, but it happens if you call -reloadData on your table view too early. Now “too early” may sound a little weird, as cell-based NSTableViews work just fine, but for example the view-based content mode doesn’t like getting a -reloadData from the -awakeFromNib method of the controller that loaded it with its NIB/XIB file.

Doing this early on makes sure that your table view breaks, even if it still seems fine afterwards as long as it is empty. As soon as you add items, however, it croaks. Also, sometimes you don’t need to call the method directly. Just get someone else to call it for you, e.g. by setting the automaticallyPreparesContent property on an NSArrayController.

Thanks to:
brettper, who filed a reproducible case in Apple’s bugreporter and posted it on OpenRadar.
Jacob Gorban, who made the connection to the NSArrayController issue.

Building a custom NSButton

CustomControlsInASidebarIn the previous article, I illustrated how one can theme NSTableView. Another control that commonly needs to be customized in themed Mac applications is NSButton. Since NSButton is a cell-based NSControl subclass, we don’t actually need to subclass it. Rather, we need to subclass NSButtonCell.

If you are using a XIB file, you can then just select the NSButton‘s NSButtonCell by clicking the button a couple of times, or by uncollapsing the button in the outline view and selecting the cell there, and setting its class to the name of our subclass.

In most cases, it is sufficient to override - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView and draw your custom button body there. NSButtonCell will take care of drawing the title, image etc.

The biggest difficulty in that case is to find out when and how to highlight your button. There are two ways a button can be highlighted, which are most obvious in a checkbox button: The actual highlight when a button is pressed is indicated by the -(BOOL) isHighlighted property.

In addition to that, a checkbox can be selected or unselected, which is indicated by its -(NSInteger) state property being set to NSOnState, NSOffState or NSMixedState. However, while every button toggles its state when clicked, not all buttons draw differently when their state is not NSOffState To find out whether you should look at the button’s state, query the -(NSInteger) showsStateBy bit mask to check whether the NSChangeGrayCell bit is set. Your button is only supposed to reflect its state if this bit is set.

If your button shape and position differs from the standard size and shape, you will also want to override - (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView to return NSCellHitContentArea | NSCellHitTrackableArea so the user doesn’t click beside your button or on its shadow to drag the window and accidentally triggers its action, or worse, click on the button to have nothing happen because the standard system button doesn’t extend as far as your custom drawing.

Usually that is all you need. You will get a custom look, but the system will provide all the correct tracking behaviour and implement accessibility actions etc. for you, swap out the title and image for the alternate title and image as needed etc.

However, sometimes you need to also adjust the title text color, e.g. because you are implementing a dark button, or because you want to reflect the button’s selected state through its text color being different from the highlighted variant. To do that, you override - (NSRect)drawTitle:(NSAttributedString*)title withFrame:(NSRect)frame inView:(NSView*)controlView. Note that the frame that is passed to this is usually already correct. Just draw your text at the origin of this rect in the font set on the cell, and you should be fine. And return the actual rectangle in which your drawing ended up.

If the standard button text positioning or image positioning doesn’t match your button’s design, there are - (NSRect)titleRectForBounds:(NSRect)theRect and - (NSRect)imageRectForBounds:(NSRect)theRect for you to override.

Finally, if you plan to create your buttons in code instead of thawing them from a XIB file, you will also have to create a subclass of NSButton and call +(void) setCellClass: (Class)inClass in its +(void) load method to tell it what cell class to instantiate.

Themeing NSTableView

Custom themed table viewWhile most Mac applications rely on the standard controls provided by MacOS X to do their work, most application developers like to follow Apple’s lead and apply their own textures, colors and fonts. And why not? Screens today have a much higher resolution and aren’t limited to basic B/W shapes. Tinting or texturing a user interface — when done with restraint and taste — helps the user find your application’s windows on multiple-window desktops more easily, and can increase recognizability of your application for other purposes.

But how does one correctly theme user interface controls with minimal interference to Apple-provided default behaviour? After all, we want our application to still look and, more importantly, behave in recognizable and familiar ways to the user. We just want it to look like a different material, or match the application’s logo and packaging better.

Let’s start with a table view. While an NSCollectionView can be easily themed by modifying various views’ color settings in Interface Builder, the best you can do for an NSTableView or its subclass NSOutlineView is set one single solid background color.

We need to write code, then. There is enough documentation for the old NSCell-based table views out there that describe how to override - (void)drawRow:(NSInteger)row clipRect:(NSRect)clipRect to theme those. So I’ll restrict myself to themeing the view-based table view variant. Most of the cells can easily be edited, but what if you want custom alternating row colors?

Luckily, NSTableRowView has a backgroundColor property that you can change. So all you need to do is make sure that you provide a - (void)tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row method in your delegate that uses the % operator to grab the corresponding color from an array of alternating row colors and sets the appropriate one as each rowView’s backgroundColor.

However, this only fixes the cells. The area below the rows, or an empty table, will still have whatever standard alternating row colors the system uses. You will have to subclass NSTableView and override - (void)drawBackgroundInClipRect:(NSRect)clipRect to fill the area below the rows.

Call -rowViewAtRow:(NSInteger)row makeIfNecessary: YES to get the last row’s NSMaxY(), if it is inside the bounds, draw alternating rectangles with a height of -(CGFloat) rowHeight underneath it until the row rect is fully out of view (start their row number at -(NSInteger) numberOfRows).

It is unfortunate that there seems to be no public equivalent to tableView:didAddRowView:forRow: in NSTableView itself. That way, one could create one subclass that takes care of the whole appearance consistently, instead having to add code for that to each delegate.

Common Cocoa Coding Patterns: UITableView row index enum

One of the things pretty much every iPhone application has is a table view containing a pre-defined list of main menu items that lead to deeper sections. Many people just hard-code this list and the item indexes, only to later find out that they need to display some rows conditionally. The code becomes a mess of conditional statements duplicated all over the place to adjust the indexes in the case that a certain item does not apply.

But there is an easier way. The first thing you do, is create an enum with the item indexes:

enum
{
    kMainTableRowInbox = 0,
    kMainTableRowTrash,
    kMainTableRowSpam,
    kMainTableNumberOfRows
};

Whenever you would use the indexes, e.g. in your table view data source and delegate methods, use these constants instead. You have the same code as before, but if you want to add/insert a new item, you can just add the constant for it in the right spot, and the rest of your code magically updates itself.

If you have one source file that implements the main list for several similar products, you can even use the preprocessor to remove items that are only needed for one device. However, what do you do if you dynamically need to add/remove items at runtime? E.g. if your application can talk to two kinds of servers, and one has a kMainTableRowTrash, but the other kind doesn’t? Simple: You create a look-up-table:

static NSUInteger          sRowLookUpTable[kMainTableNumberOfRows] = { 0 };
static NSUInteger   sRowLookUpTableSize = 0;

-(void) rebuildRowLookUpTable
{
    NSUInteger  actualRowNumber = 0;
    for( NSUInteger virtualRowNumber = 0; virtualRowNumber < kMainTableNumberOfRows; virtualRowNumber++ )
    {
        if( virtualRowNumber == kMainTableRowTrash && ![self haveTrash] )
            continue;
        sRowLookUpTable[actualRowNumber] = virtualRowNumber;
        actualRowNumber++;
    }

    sRowLookUpTableSize = actualRowNumber;
}

Call this in your init method(s), or whenever some state changes that may affect which rows should be shown. Change your table view delegate methods to use sRowLookUpTableSize instead of kMainTableNumberOfRows for the number of rows. And whenever you look at an index to compare it to one of the row index constants, do

sRowLookUpTable[indexPath.row]

instead of just

indexPath.row

to translate the real row index into one of the constants that indicate what content you want displayed. This way, most of your code never needs to know in which order which items are actually shown in your table. It just needs to be able to display all kinds of rows, and only -rebuildRowLookUpTable needs to actually know which rows are hidden or visible.

Also, the constant names make it obvious what row a bit of code is dealing with. If, two years after you wrote an app on contract, the customer comes back and wants it updated for MacBook Airs with iOS, and remove the settings category, you can just search for a kMainTableRowSettings constant in the text editor and get rid of all that code. Or just move the constant below the kMainTableNumberOfRows constant. All the code is still there, compiles, but the index will never be added to the table.

Playing with Objective C on Debian

[Debian showing Objective C source code in gedit]

I felt like playing with Linux a bit, so I went and installed Debian on a partition. Apart from a few failed attempts to install it on an external drive (something which works fine with MacOS X, so I was spoiled) and a bit of confusion when it asked me for my drive name (how would I know a cryptic character combination like hdb4? And I selected that drive in your UI before, can’t you let me use that same selector again?), it went pretty smooth.

Once having installed Debian, I wanted to play a little with GCC on there. However, by default, like a nice desktop OS, the developer tools weren’t installed, so I opened a root Terminal window and typed in

apt-get install gcc cpp binutils libc6-dev make gobjc

Most of the items after install are what any web site on Debian will tell you is needed to use GCC: GCC itself, the C preprocessor, binutils (mainly for the ld linker and the as assembler), the C standard library and the make command line tool for making it easier to build complex build commands (think a command line version of Xcode project files).

But the last one, gobjc, installs the GNU Objective-C runtime and compiler. This is only the runtime with the old Object base class, i.e. without -retain and -release. You get Object by including objc/Object.h. You’ll also want to add a -lobjc option to your GCC command line, or you’ll get lots of error message about missing objc_msgSend() etc.

These headers get installed in /usr/lib/gxx/x86_64-linux-gnu/4.3/include (or whatever GCC version you installed, and whatever architecture your Mac has), in case you want to find out how Object looks..

To get a more familiar Foundation “framework”, I built and installed libNuFound, a Foundation clone that works alongside the GNU runtime, written for use with the Nu programming language. The basic installation is detailed on their github page, essentially the traditional

./configure
make
make install

dance, except that you need to copy the headers yourself:

cp -r Foundation /usr/local/include

Then, if you wanted to build a Foundation tool whose source code is in a file main.m, what you need to do is:

export LD_RUN_PATH="$LD_RUN_PATH:/usr/local/lib"gcc main.m -lobjc -lNuFound -lm -ldl -fconstant-strings-class=NSConstantString

The thing with LD_RUN_PATH is needed so the linker can write the full path of the library into the executable. Otherwise you get an error like

error while loading shared libraries: libNuFound.so.0: cannot open shared object file:No such file or directory

There are other options to solve this problem that make will tell you about when you build/install libNuFound. The -lobjc option pulls in the GNU ObjC library, -lNuFound grabs the Foundation library we just built, and -lm and -ldl grabs the standard C math library and a code-loading library needed by libNuFound. The last parameter tells the ObjC compiler that Objective C string constants like @”Cool” should generate NSConstantString objects, not the old String flavor.

But hey, now I have a Debian installation that runs Objective-C code. Neat :-) No UI libraries, though.

Update: Note that you will probably want to install this on a 32-bit CPU with a 32-bit Debian. With some investigation, Mr. Mo and me found that libNuFound seems to have a few bugs on 64-bit CPUs at the moment.