Cocoa with Love

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

HashValue: an object for holding MD5 and SHA hashes

Hash values are small, convenient values that you can generate from larger blocks of data for easy indexing, sorting and tracking. The traditional approach for generating MD5 and SHA hashes on Unix platforms to is to use command-line programs like openssl and md5. Apple provide easier approaches in the CommonCrypto library: here's how to use it, along with an NSValue subclass to wrap the result for interoperability with other Cocoa classes.

Introduction to hashes

A hash value is a small, convenient number used to track or sort an arbitrary block of data.

A real-world example of a hash value is the initial letter in a word. You can use the initial letter of a word to lookup that word in a dictionary. If two words have different starting letters, they cannot be equal but if two words have the same starting letter, that doesn't guarantee they are the same.

For fast searching, you can immediately see the problem with only using an initial letter: if all you had to look up a word was its initial letter, you'd still have thousands of words to go through that all start with the same letter. You could use the first four letters but some combinations will be rare (like "aard") but others will contain hundreds of matches (like "stra").

In computing, we rarely ever use the first values in a block of data to track that block of data. Starting values of blocks of data are too often the same or similar — especially in the common case where we are sorting data that already has traits in common.

Instead, we use hash functions that use relatively complex mathematics to generate values from the source data that are well spread, even for source data that is nearly identical. Fortunately, you don't need to know the underlying mathematics, all you need to know is that a hash value can be used to:

  • check if two blocks of data are the same
  • sort data into hash tables
  • checksum data (make certain your data hasn't changed)

Though these are the main purposes for which you should use hashes, MD5 and SHA hashes were actually developed for cryptography, not basic data handling. Nevertheless, for encryption and password handling in your own applications, I recommend using the Keychain (Security.framework) rather than manually using cryptographic hashes.

Generating an MD5

MD5 is one of the most common hash functions. While it is no longer considered safe for security, its use as a checksum is very common.

The traditional Unix approach is to use the md5 program on the command-line:

matt$ md5 -s "Some data value."
MD5 ("Some data value.") = db7116c8634ad7fe3bd90bee94274ee0

The 32 character hexadecimal string is a human readable representation of the 16 byte output of the MD5 function.

On the Mac and iPhone, we can generate this value as follows:

#import <CommonCrypto/CommonDigest.h>

char input[] = "Some data value.";
char result[16];
CC_MD5(input, strlen(input), result);

However, we frequently want the human-readable hexadecimal string. The following will produce an identical ouput to the previous command-line invocation:

printf("MD5 (\"%s\") = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
    input,
    result[0], result[1], result[2], result[3], 
    result[4], result[5], result[6], result[7],
    result[8], result[9], result[10], result[11],
    result[12], result[13], result[14], result[15]);

Producing other kinds of hash works in the same way. e.g. For SHA256, use CC_SHA256 instead of CC_MD5 and increase the size of the result to 20 from 16.

The HashValue class

Since hash values are frequently used to track blocks of data in a program, it would be nice to have an Objective-C class that wraps the hash values so we can use them in NSDictionary objects as keys for our data.

If we consider a hash value simply as a small C struct, i.e:

typedef struct
{
    char value[CC_MD5_DIGEST_LENGTH];
} HashValueMD5Hash;

typedef struct
{
    char value[CC_SHA256_DIGEST_LENGTH];
} HashValueShaHash;

then the easiest way to make it a fully fledged Objective-C object is to create an NSValue from it:

char input[] = "Some data value.";
HashValueMD5Hash result;
CC_MD5(input, strlen(input), &result);

NSValue *myHashValue = [NSValue valueWithBytes:&result objCType:@encode(HashValueMD5Hash)];

That's an okay solution but if you're generating a lot of hashes in your program, it would be good to have a class that:

  • has an optimized construction method that can generate the hash directly from NSData
  • abstracts away the C struct so you can deal exclusively with the Objective-C objects
  • overrides the description method to easily generate human-readable strings

So I wrote the HashValue class.

@interface HashValue : NSObject <NSCoding, NSCopying>
{
    unsigned char value[HASH_VALUE_STORAGE_SIZE];
    HashValueType type;
}

- (id)initMD5HashWithBytes:(const void *)bytes length:(NSUInteger)length;
+ (HashValue *)md5HashWithData:(NSData *)data;
- (id)initSha256HashWithBytes:(const void *)bytes length:(NSUInteger)length;
+ (HashValue *)sha256HashWithData:(NSData *)data;

- (const void *)value;
- (HashValueType)type;

@end

Despite being a class that wraps a value, there's no explicit reason to make it a subclass of NSValue. Since subclassing NSValue has inherent difficulties (you need to carefully override a lot of inherited methods) I've made the class a basic subclass of NSObject.

The init method implementations are fairly simple:

- (id)initMD5HashWithBytes:(const void *)bytes length:(NSUInteger)length
{
    self = [super init];
    if (self != nil)
    {
        CC_MD5(bytes, length, value);
        type = HASH_VALUE_MD5_TYPE;
    }
    return self;
}

The description method is overridden to provide the human-readable hexadecimal string:

- (NSString *)description
{
    NSInteger byteLength;
    if (type == HASH_VALUE_MD5_TYPE)
    {
        byteLength = sizeof(HashValueMD5Hash);
    }
    else if (type == HASH_VALUE_SHA_TYPE)
    {
        byteLength = sizeof(HashValueShaHash);
    }

    NSMutableString *stringValue =
        [NSMutableString stringWithCapacity:byteLength * 2];
    NSInteger i;
    for (i = 0; i < byteLength; i++)
    {
        [stringValue appendFormat:@"%02x", value[i]];
    }
    
    return stringValue;
}

Most of the other methods in the class are basic accessors or NSCopying, NSCoding and NSObject methods. The copying methods in particular are essential so that the object can be used as a key in an NSDictionary.

I will highlight one other method:

- (NSUInteger)hash
{
    return *((NSUInteger *)value);
}

You may wonder why it's necessary to have a hash method on a class that is itself a hash value. Hash methods in Cocoa are used for the same indexing and sorting tasks I identified above: sorting and finding objects in NSSet and NSDictionary. In Cocoa the default hash method calculates its hash value from the memory address of the object. Because we have overridden isEqual: to compare the object's internal value, we also need to override the hash method to also reflect this change. This is a basic requirement of hashes — equal objects must return the same hash value (imagine the confusion if two identically spelled words were sorted to different locations in a dictionary).

It may seem a little odd to simply return the first few bytes of the value as our new hash (after I explained that the first few bytes is rarely the best hash) but this case is an exception to the rule: our data is already "well-spread" and every bit in our hash is as well-spread as the next.

Conclusion

You can download the HashValue class as a .zip file (2kB)

Hash values are used everywhere. Git uses SHA1 to track file changes in its repository, BitTorrent uses MD5s to identify torrents and many download programs use hashes to checksum downloaded data.

The CommonCrypto library (part of Foundation on the Mac and iPhone through libSystem) makes generating common hash functions very simple.

As with all data manipulation, I think a nice Cocoa class around the data makes it easier to use. I have only added MD5 and SHA256 to this particular implementation but it should be very simple to add other CommonCrypto hashes to the class should you require them.

Read more...

Custom views in Interface Builder using IBPlugins

If you have custom views configured in code, it can be time consuming to configure them for each instance and make them look right in context. To make the process smoother, you can create Interface Builder plugins and configure your objects in Interface Builder. While the Xcode documentation explains how to do this, it is long, thorough and confusing. Here is the simplified set of steps that I use to create Interface Builder plugins quickly.

Introduction

Apple do have extensive documentation on Interface Builder Plugin creation. However, their documentation is thorough enough that may be overwhelming the first time you want to write an Interface Builder plugin.

I also find the workflow in Apple's IBPluginGuide very different to my typical workflow. I think this is because I normally just want an existing class to show up in Interface Builder so I can tweak one or two attributes — the processes for creating a redistributable library of components is more than I need.

So I was inspired to write this post: a shorter, workflow-optimised version of the same process described in the IBPluginGuide — using Interface Builder to configure a custom button.

A custom buttom

Consider the button in the following window:

ibplugin1.png

A big, drab, gray button. Maybe gray is an acceptable default but it doesn't really match this window. This post will make it easy to adjust this color in Interface Builder.

The large gray button here uses a custom button cell which draws the button using the Gloss Gradient from one of my earlier posts. The drawing code is:

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    NSBezierPath *roundRectPath =
        [NSBezierPath
            bezierPathWithRoundedRect:NSInsetRect(cellFrame, 2, 2)
            xRadius:5
            yRadius:5];

    NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
    [graphicsContext saveGraphicsState];
    [roundRectPath addClip];

    DrawGlossGradient(
        [graphicsContext graphicsPort],
        self.buttonColor, // <-- this determines the color of the button
        cellFrame);

    if ([self isHighlighted])
    {
        [[NSColor colorWithCalibratedRed:0.0 green:0.15 blue:0.35 alpha:0.5]
            set];
        [roundRectPath fill];
    }
    [graphicsContext restoreGraphicsState];

    [[NSColor lightGrayColor] set];
    [roundRectPath setLineWidth:2.0];
    [roundRectPath stroke];

    [self drawInteriorWithFrame:cellFrame inView:controlView];
}

This is all fine except that the color of the button is determined by the self.buttonColor property and if we have to choose this in code (continually changing the value, fixing, continuing, refreshing and repeating) it could get very time consuming.

A better solution would be to edit the button's color in Interface Builder. That way, we will be able to use color sliders to update the button drawn in the complete context of the window, in real-time.

Creating the IBPlugin project

My process normally starts by creating a custom view component. In this case, I have already created a class named CustomButtonCell in the project for my main application (AppWithButton). After creating the class, I have decided it would be a good idea to have an Interface Builder Plug-In.

A quick point about class requirements: every property we want to configure in Interface Builder must be encoded and decoded for the object using implementations of the NSCoder protocol methods initWithCoder: and encodedWithCoder: overrides. Download the project linked below to see how this is done.
1. Create and name the project

"Interface Builder Plug-In" is a project template in Xcode. In the New Project window, it's in the "Mac OS X -> Standard Apple Plug-ins" section.

An important point to consider is the name for the project — it should not be the same as the custom view component (in this case, CustomButtonCell) because the template will create a class with the name and it can't conflict with the existing view component.

I chose "ButtonPlugin" and saved the new project in the folder for my existing AppWithButton project.

2. Make the new project use the existing CustomButtonCell
Delete the default files and insert our own

The template creates a custom view in the ButtonPlugin project. I never use this (since I want to use my existing view). So I delete the ButtonPluginView.m, ButtonPluginView.h references and files.

I add my CustomButtonCell.m and CustomButtonCell.h files to the ButtonPlugin project but I don't copy or move the files — I leave the files at their current locations in AppWithButton project but drag them into the ButtonPlugin's Source Tree.

Make certain these new files get built

You need to check that the CustomButtonCell.m is added to the Compile Sources build phase of the ButtonPluginFramework Target and the CustomButtonCell.h is added to the Copy Headers build phase of the ButtonPluginFramework. Neither should appear in the ButtonPlugin target.

Then, select the "CustomButtonCell.h" file from the "Copy Headers" build phase and in the Detail View, change the "Role" from "Project" to "Public". This is a pretty obscure thing to do. I normally don't have the Detail View visible — if you don't know which view is the Detail View, it's time to learn because there is no other way to change this value in Xcode.

ibplugin3.png

Change the Role of the "CustomButtonCell.h" to "public" in the Detail View

Rename the file ButtonPluginViewIntegration.m to CustomButtonCellIntegration.m and replace every occurrence of ButtonPluginView in this file to CustomButtonCell.

3. Prepare all the other files in the project

Make the following file changes:

  1. Find the ButtonPluginView.classdescription and rename this file to CustomButtonCell.classdecription (same as our custom cell).
  2. In the contents of this file, change the ClassName to match the actual class name CustomButtonCell and change the SuperClass to be NSButtonCell (again, matching the actual super class for our custom button cell).
  3. In ButtonPlugin.m (the top level class in the ButtonPlugin project), set the bundle identifier to something appropriate. I used com.mattgallagher.ButtonPlugin — this needs to be unique among Interface Builder plugins, so you pick an appropriate value each time.
  4. Set the bundle identifier in the Info.plist and the ButtonPlugin-Info.plist to the same com.mattgallagher.ButtonPlugin value.
4. Configure the display of the button cell for the Interface Builder Library panel

Open the ButtonPluginLibrary.nib. This file contains the "Library Object Template" view (an instance of IBLibraryObjectTemplate). You can find it in the "Library Objects" view at the top level.

Delete the library template that doesn't apply

The Library Object Template will contain a "Template" and an "Example" square. The "Template" version is for NSView subclasses but our CustomButtonCell needs to be embedded in another object (an NSButton) so we will use the "Example" square — so delete the "Template" square.

Set our custom class in the library template

If you click on the button in the "Example" square then click again, it will select the NSButtonCell inside the button (these clicks should be slower than a double-click, since a double-click will edit the text of the NSButton instead of selecting the NSButtonCell inside). With the NSButtonCell selected:

  1. Type Command-6 to select the correct inspector panel.
  2. Enter the custom class name in the "Class" field of the inspector — in our case, we need this to be CustomButtonCell.
  3. Set the button cell class for the NSButton to the right of the "Example" box in the same way.

Select the Library Object Template (ButtonPluginLibrary.nib window -> Library Objects -> Library Object Template) and:

  1. Type Command-1 to select the correct inspector panel.
  2. Fill in the "Label", "Summary" and "Description" for your Library Object as you choose. I like to delete the Path and leave it blank but you can add a path if you want to categorize your custom classes.
5. Configure the Interface Builder Inspector panel

Back in the ButtonPlugin project again, open the ButtonPluginInspector.xib.

Set all the controls in the Inspector panel how we want them

I deleted everything in the "Inspector View" window except 1 label and the NSColorWell. I moved these controls to the top of the view and then made the view 35 pixels high.

Connect the controls so they act on our object

To make the color selector do something, I used bindings. Select the NSColorWell and:

  1. Type Command-4 to select the correct inspector panel.
  2. Under the "Value" subheading, bind to File's Owner (make sure the checkbox is selected too).
  3. Set the Model Key Path to inspectedObjectsController.selection.buttonColor.

This binding needs one other change to work. Back in the ButtonPlugin project, open the CustomButtonCellIntegration.m file. Change the [[keyPaths objectForKey:IBAttributeKeyPaths... line to:

[[keyPaths objectForKey:IBAttributeKeyPaths]
    addObjectsFromArray:[NSArray arrayWithObjects:@"buttonColor", nil]];

This tells Interface Builder to track and monitor the buttonColor property on the CustomButtonCell class. It does not actually perform the value changing (the binding we established will change the value directly) but it will make certain that this value will be tracked for undos and can be edited correctly.

Using the IBPlugin

At this point, you can run the ButtonPlugin project and it will launch Interface Builder with the plugin visible. The only problem is that the plugin won't be visible if you launch Interface Builder in any other way.

Build Settings

The following steps will make the ButtonPlugin project build the ButtonPlugin.framework and ButtonPlugin.ibplugin and install it in your Library.

Double click the ButtonPlugin project item in the ButtonPlugin project Source Tree to edit the project settings. Select the "Build" tab, then choose "Configuration: All Configurations". Then make the following changes:

  1. Set the "Deployment Location" checkbox to checked.
  2. Set the "Installation Build Products Location" to "$(HOME)/Library/Frameworks".
  3. Set the "Installation Directory" to "/".

Double-click the "ButtonPlugin" target in the Source Tree to edit that target's settings. Select the "Build" tab, then choose "Configuration: All Configurations". Then make the following change:

  1. Set the "Installation Directory" to "/ButtonPlugin.framework/Resources.
And now it's installed

With these changes made, build and run the ButtonPlugin project and it will install the ButtonPlugin.framework in your ~/Library/Frameworks directory and load it in Interface Builder. From now until you remove the framework from your library, it will remain in Interface Builder and you can use it at any time.

I realize that this configures the app to install the "Debug" build in the user's library, over the top of the "Release" build (if the Release build is already built) but this is really just for local use, so I don't really care. If you do care, you might not want to apply these settings to all configurations. For me: this is faster to implement and easier to manage.

Integration with the original AppWithButton project

After setting up the Interface Builder plugin, instance of CustomButtonCell in your existing .xib and .nib files will not instantly update. You'll probably need to create new versions of the cell by dragging them out from the Library.

In this example, I have chosen to not link the original AppWithButton project with the ButtonPlugin.framework. This is because I don't want to distribute either the framework or the plugin — they are both for my purposes only.

If you wanted to link them, you could remove the CustomButtonCell.m and CustomButtonCell.h files from the original project and replace them with the ButtonPlugin.framework. According to the Xcode documentation, this arrangement would allow you to avoid installing the ButtonPlugin.framework in your ~/Library/Frameworks directory (Interface Builder would automatically find the plugin for any .nib or .xib file in the project). That's a nice idea but it has never worked for me, so I never bother.

Set a build dependency to keep ButtonPlugin up-to-date

Instead, I like to drag the ButtonPlugin.xcodeproj file into the AppWithButton Source Tree and edit the AppWithButton target, go to the "General" tab and add the ButtonPlugin.xcodeproj as a Direct Dependency.

The reason for this is that if I change the CustomButtonCell class and rebuild, it will automatically rebuild the Interface Builder plugin accordingly (you need to restart Interface Builder to see the changes).

ibplugin2.png

The AppWithButton window in Interface Builder, adjusting the color of the button in real-time.

Conclusion

You can download the complete AppWithButton project zip file (including the ButtonPlugin project) (385kB).

It takes quite a few steps to set up an Interface Builder plugin. Fortunately, they're all simple, if a little menial.

Notice how little code was actually written though: bindings and Objective-C 2.0 properties make this whole process considerably easier — there is no actual code written to set the buttonColor (except in the NSCoder method implementations) since the bindings do it all for us.

Once you're practiced at making plugins in this way, the effort to create one may be justified, even just to tweak simple properties like this.

Do I know how to do this for Cocoa Touch classes for iPhone development? No. I imagine it's possible but you'd need to completely change the IBPlugin project from the template and I've never tried.

Read more...

Verifying that a string contains an email address using NSPredicate

To celebrate the official release of iPhone OS 3.0 this week, I will show you how to verify that an NSString contains a syntactically valid email address using NSPredicate — a class that joins the iPhone SDK 3.0 as part of the Core Data additions. This code will work on Mac OS X too since, as with the rest of Core Data, NSPredicate has been part of Mac OS X since 10.4 (Tiger).

Before I begin...

I gave an interview to Anthony Agius of MacTalk.com.au this week. You can download the MP3 from their website. I'm hesitant to listen to my own voice but I think I talked about what it's like to be an independent Mac/iPhone developer in Melbourne, Australia.

Back to predicates

In programming, a predicate is a condition that returns true or false if the object it processes has the properties that the predicate describes. The key difference between a predicate and a regular boolean expression is that a predicate only considers the properties of one object, where a boolean expression may consider multiple, unrelated objects.

Many programmers are familiar with predicates as used in SQL database queries. For example a query to extract the complete row from the "people" database table for every person named "John Smith" might look like this in SQL:

SELECT * FROM people WHERE firstname = 'John' AND lastname = 'Smith'

Everything after the "WHERE" is the predicate — it looks at properties of the row only and is either true (the row will be extracted) or false (the row will be ignored).

Using NSPredicate to evaluate predicates

In Cocoa, NSPredicate works in much the same way as the "WHERE" clause of SQL. The main reason that NSPredicate is being brought to the iPhone is that NSPredicate fulfils the same role in Core Data that "WHERE" clauses fulfil in SQL — to allow the persistent store to fetch objects that satisfy specific criteria.

Imagine we had an NSDictionary created using the following method:

- (NSDictionary *)personRowWithFirstname:(NSString *)aFirstname
    lastname:(NSString *)aLastname
{
    return
        [NSDictionary dictionaryWithObjectsAndKeys:
            aFirstname, @"firstname",
            aLastname, @"lastname",
        nil];
}

we could test if a given row created by this method matched the predicate "firstname = 'John' AND lastname = 'Smith'" with the following:

// given an NSDictionary created used the above method named "row"...
NSPredicate *johnSmithPredicate =
    [NSPredicate predicateWithFormat:@"firstname = 'John' AND lastname = 'Smith'"];
BOOL rowMatchesPredicate = [johnSmithPredicate evaluateWithObject:row];

The string format used to construct an NSPredicate in Cocoa is very similar to the syntax of the "WHERE" clause in SQL. You can also construct this NSPredicate in code by building it from two NSComparisonPredicates and an NSCompoundPredicate.

A more common use of NSPredicate is filtering — extracting rows that match an NSPredicate from a larger collection:

// given an NSArray of rows named "rows" and the above "johnSmithPredicate"...
NSArray *rowsMatchingPredicate = [rows filteredArrayUsingPredicate:johnSmithPredicate];

This is then more like an SQL query where we have selected matching rows from the larger table of data.

Note: NSPredicate handles filtering only. If you'd like to replicate SQL's "ORDER BY" clause, you can apply NSSortDescriptor as a separate step.

Verifying an email address

The "LIKE" comparison operator in NSPredicate (NSLikePredicateOperatorType) is commonly used as a convenient means of testing if an NSString matches a Regular Expression. It's advantage over full libraries with greater options and replacement capability is that it is already in Cocoa — no libraries, no linkage, no hassle.

To test if an NSString matches a regular expression, we can use the following code:

NSPredicate *regExPredicate =
    [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regularExpressionString];
BOOL myStringMatchesRegEx = [regExPredicate evaluateWithObject:myString];

The only question that remains is: what is a regular expression that can be used to verify that an NSString contains a syntactically valid email address?

NSString *emailRegEx =
    @"(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
    @"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
    @"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
    @"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
    @"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
    @"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
    @"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";

This regular expression is adapted from a version at regular-expressions.info and is a complete verification of RFC 2822.

This adaptation involved escaping all backslashes with another backslash (otherwise the NSString will try to interpret them before they are used in the Regular Expression) and escaping the ampersands (&) so it isn't interpreted as a Unicode escape sequence and caret (^) characters because — actually I have no idea why except that the expression wouldn't parse without it.

The linked regular-expressions.info page recommends using slightly different regular expressions that force the top-level domain to be a country code or a known top-level domain. With the number of top-level domains due to increase in the near future, I'm not sure this is a good constraint to impose — since this check isn't intended to verify that the provided domain name is valid.

Since this regular expression NSString is so long, I've split it over 7 lines. This is an underused feature in Standard C languages — if you split a string into pieces but put nothing except whitespace between the pieces, the compiler will treat it as one continuous string. You don't need to write an extremely long string on a single long line.

Conclusion

Just a few lines of code this week but I thought it would be good to draw attention to one of the minor additions making its way to the iPhone in SDK 3.0. I use NSPredicate all the time on Mac OS to perform searches, extract subarrays and perform quick Regular Expression tests. Without it, the only alternatives on the iPhone were methodical array iterations and manual comparisons in code.

Read more...

Revisiting an old post: Streaming and playing an MP3 stream

Given the attention it received and the number of bugs I know it contained, I wanted to revisit an old post of mine: Streaming and playing an MP3 stream. In this post, I'll talk about the problems the original contained, how I fixed those problems and I'll present the updated result.

Introduction

Last September, I wrote a post titled "Streaming and playing an MP3 stream". The post was largely an experiment — I just wanted to see if I could play a streaming MP3 by quickly adapting Apple's AudioFileStreamExample to accept an HTTP data stream.

Unexpectedly, the post became one of my most popular. The attention quickly revealed the limitations in my approach:

  • The blend of Objective-C and C was muddled and led to a situation where neither were being used cleanly.
  • The boolean flags I copied from the original example were a bad way to describe the playback state and lots of situations were not covered by these flags.
  • Sending notifications to the user-interface on a thread that isn't the main thread causes problems.
  • The extra thread I added (the download thread) was never thread-safe.

I've finally decided to take the time to present a solution to these issues and present an approach which is a little more robust and a little easier to extend if needed.

You can download the complete AudioStreamer project as a zip file (around 110kB) which contains Xcode projects for both iPhone and Mac OS. You can also browse the source code repository.

Limited scope

One point should be clarified before I continue: this class is intended for streaming audio. By streaming, I don't simply mean "an audio file transferred over HTTP". Instead, I mean a continuous HTTP source without an end that continues indefinitely (like a radio station, not a single song).

Yes, this class will handle fixed-length files transferred over HTTP but it is not ideal for the task.

This class does not handle:

  1. Buffering of data to a file
  2. Seeking within downloaded data
  3. Feedback about the total length of the file
  4. Parsing of ID3 metadata

These things often can't be done on streaming data, so this class doesn't try. See the "Adding other functionality" section for hints about how the class could be reorganised to handle some of these features.

Taking code out of C functions

Since I had borrowed the AudioFileStream and AudioQueue callback functions from Apple's example, they were Standard C.

My first change was to make these 6 callback functions (7 including the CFReadStream callback) little more than wrappers around Objective-C methods:

void MyPacketsProc(
    void *inClientData,
    UInt32 inNumberBytes,
    UInt32 inNumberPackets,
    const void *inInputData,
    AudioStreamPacketDescription *inPacketDescriptions)
{
    // this is called by audio file stream when it finds packets of audio
    AudioStreamer* streamer = (AudioStreamer *)inClientData;
    [streamer
        handleAudioPackets:inInputData
        numberBytes:inNumberBytes
        numberPackets:inNumberPackets
        packetDescriptions:inPacketDescriptions];
}

At a compiled code level, this is a step backwards: all I've done is slowed the program down by an extra Objective-C message send.

Technically, a C function that takes a "context" pointer (like the inClientData pointer here) is not significantly different to a method. What a method does is makes data hiding and data abstracted actions easier. Within a method, you can easily access the instance variables of an object and you don't need to explicitly pass context into each function.

This is the cliché argument in favor of object-orientation — but it isn't why I reorganized these functions and methods.

The honest reason why I did it is aesthetics: it is easier to read a class that is implemented using Objective-C methods alone — it's more consistent. I chose to move towards an Objective-C aesthetic and away from the Standard C aesthetic of the CoreAudio sample code to promote consistent formatting, consistent means of accessing state variables, consistent ways of invoking methods and consistent ways of synchronizing access to the class.

Describing state

With the majority of code now inside the class, I was in a better position to start handling changes through methods rather than direct member access.

My original approach to state came from Apple's original example. This example had just one piece of state: a bool named finished (which indicated that the run loop should exit).

The problem with this flag is how simple it is. It is unable to distinguish between the following:

  1. End of file, normal automatic stop.
  2. The user has asked the AudioStreamer to stop but the AudioQueue thread has not yet responded.
  3. An error has occurred before the AudioQueue thread is created and we must exit.
  4. We are stopping the AudioQueue for temporary reasons (clearing it, changing device, seeking to a new point) but we don't want the loop to stop.

For Apple's example, there was no problem: the first case was the only one that ever occurred.

As a hasty solution, I had added started and failed flags but these really only covered the first and third case adequately.

In the end, I realized that the AudioStreamer needed much more descriptive state where every combination of progress within each thread had a different position:

typedef enum
{
    AS_INITIALIZED = 0,
    AS_STARTING_FILE_THREAD,
    AS_WAITING_FOR_DATA,
    AS_WAITING_FOR_QUEUE_TO_START,
    AS_PLAYING,
    AS_BUFFERING,
    AS_STOPPING,
    AS_STOPPED,
    AS_PAUSED
} AudioStreamerState;

and when stopping, one of the following values would also be needed:

typedef enum
{
    AS_NO_STOP = 0,
    AS_STOPPING_EOF,
    AS_STOPPING_USER_ACTION,
    AS_STOPPING_ERROR,
    AS_STOPPING_TEMPORARILY
} AudioStreamerStopReason;

In this way, the state always describes where every thread is and the stop reason explains why a transition is occurring.

Combining this with an error code that replaces the old failed flag, I now have a complete desription of the state.

By cleaning up the state of the object, I was able to make the object capable of state transitions that weren't previously possible including pausing/unpausing and returning to the AS_INITIALIZED state after a stop (instead of requiring that the class be released after stopping).

Notifications

In the old version of the project the only way for the user-interface to follow the playback state was to observe the isPlaying property on the object which reflected the kAudioQueueProperty_IsRunning property of the AudioQueue.

This observing was handled through KeyValueObserving. I'm a big fan of KeyValueObserving for its simplicity and ubiquity but this was not the correct place to use it.

KeyValueObserving always invokes the observer methods in the same thread as the change. Since all changes in AudioStreamer happen in secondary threads, this means that the observer methods were getting invoked in secondary threads.

Why is this bad? A minor drawback is simply the unexpectedness for the observer but the biggest reason was that the sole purpose of observing this property was to update the user-interface and the user-interface on the iPhone cannot be updated from any thread except the main thread. Even on the Mac, performing updates off the main thread can have unexpected and glitchy results.

The solution is to retain the NSNotificationCenter of the thread that first calls start on the object and use this center to send messages as follows:

NSNotification *notification =
    [NSNotification
        notificationWithName:ASStatusChangedNotification
        object:self];
[notificationCenter
    performSelector:@selector(postNotification:)
    onThread:[NSThread mainThread]
    withObject:notification
    waitUntilDone:NO];

Don't invoke postNotification: directly from the secondary thread as, like most methods, it is not thread safe and it could be in use from the main thread.

Thread safety

Despite adding an extra thread on top of Apple's AudioFileStreamExample, I never really spent any time thinking about thread safety — a reckless approach to stability. In my defence Apple's example wasn't exactly cautious with its threads and would quit while the AudioQueue's thread was still playing the last buffer.

The most efficient approach to threading is to carefully enter @synchronized (or NSLock or pthread_mutex_lock) in a tight region around any use of a shared variable.

Unfortunately for the AudioStreamer class, almost everything in the class is shared. Instead, I decided to go for the decidedly less efficient approach of running almost everything in the class within a @synchronized section, emerging only at points when control must be yielded to other threads.

The drawback is that the code rarely runs simultaneously on multiple threads (although threading here is for blocking and I/O, not for multi-threaded performance reasons so that's not a probem). The advantage with this heavy-handed locking approach is that the only threading condition that may cause problems are deadlocks.

When do deadlocks occurs? Only when you're waiting for another thread to do something while you're inside the synchronized section needed by that other thread. The simple solution: never wait for another thread inside a synchronized section.

AudioStreamer has three situations where 1 thread waits for another:

  1. The run loop (the AudioFileStream thread waits for any kind of control communication from the main thread or playback finished notification from the AudioQueue thread).
  2. The enqueueBuffer method (AudioFileStream thread waits for the AudioQueue thread to free up a buffer).
  3. Synchronous AudioQueueStop invocations (waits for the AudioQueue to release all buffers).

The first two points are easy: perform these actions (any any method invocation which invokes them) outside of the @synchronized section.

The final point is harder: the synchronous stop must be performed inside the @synchronized section to prevent multiple AudioQueueStop actions occurring at once. To address this, the release of buffers by the AudioQueue (in handleBufferCompleteForQueue:buffer:) must perform its work without entering the @synchronized section (although it's allowed to use the queueBuffersMutex as normal since that isn't used by anything else during a synchronous stop).

Of course, every time the @sychronized section is re-entered, a check must be performed to see if "control communication" has occurred (the class checks this by invoking the isFinishing method and exiting if it returns YES).

Adding other functionality

Get metadata

The easiest source of metadata comes from the HTTP headers. Inside the handleReadFromStream:eventType: method, use CFReadStreamCopyProperty to copy the kCFStreamPropertyHTTPResponseHeader property from the CFReadStreamRef, then you can use CFHTTPMessageCopyAllHeaderFields to copy the header fields out of the response. For many streaming audio servers, the stream name is one of these fields.

The considerably harder source of metadata are the ID3 tags. ID3v1 is always at the end of the file (so is useless when streaming). ID3v2 is located at the start so may be more accessible.

I've never read the ID3 tags but I suspect that if you cache the first few hundred kilobytes of the file somewhere as it loads, open that cache with AudioFileOpenWithCallbacks and then read the kAudioFilePropertyID3Tag with AudioFileGetProperty you may be able to read the ID3 data (if it exists). Like I said though: I've never actually done this so I don't know for certain that it would work.

Stream fixed-length files

The biggest variation you may want to make to the class is to download fixed-length files, rather than streaming audio.

To handle this, the best approach is to remove the download from the class entirely. Download elsewhere and when "enough" (an amount you should determine on your own) of the file is downloaded, start a variation of the class that plays by streaming from a file on disk.

To adapt the class for streaming from a file on disk, remove the CFHTTPMessageRef and CFReadStreamRef code from openFileStream and replace it with NSFileHandle code that uses waitForDataInBackgroundAndNotify to asynchronously stream the file in the same way that CFReadStreamRef streamed the network data.

Once you're streaming from a file, you'll probably want to permit seeking within the file. I've already put hooks within the file to seek (set the seekNeeded flag to true and set the seekTime to the time in seconds to which you want to seek) — however, the mechanics of seeking within the file would be dependent on how you access the file.

Incidentally, the AudioFileStreamSeek function seems completely broken. If you can't get it to work (as I couldn't) just seek to a new point in the file, set discontinuous to true and let AudioFileStream deal with it.

Handling data interruptions

At the moment, if the AudioQueue has no more buffers to play, the state will transition to AS_BUFFERING. At this point, no specific action is taken to resolve this situation — it assumes that the network will eventually resume and requeue enough buffers.

I actually expect there will be cases where this action is insufficient — you may need to ensure that the AudioQueue is paused until enough buffers are filled before resuming or even restart the download entirely. I haven't experimented much since it is easiest with streaming audio just to stop and start new.

Incidentally, if you're curious to know how many audio buffers are in use at any given time, uncomment the NSLog line in the handleBufferCompleteForQueue:buffer: method. This will log how many 1 kilobyte audio buffers are queued waiting for playback (when the queue reaches zero, the AudioStreamer enters the AS_BUFFERING state).

Conclusion

You can download the complete AudioStreamer project as a zip file (around 110kB) which contains Xcode projects for both iPhone and Mac OS. You can also browse the source code repository.

The functionality of this new version has not changed greatly — my purposed was to present a version that is more stable and tolerant of unexpected situations, rather than add new features.

As before, the AudioStreamer class should work on Mac OS X 10.5 and on the iPhone (SDK 2.0 and greater).

The source repository is hosted on github so you can browse, fork or track updates as you choose. I will likely update again in future (I can't imagine I've written this much code without causing more problems) and this way, you can see the changes I've made.

I hope this post has shown you a number of problems that can happen when code is written hastily. This doesn't mean you should always avoid hastily written code (timeliness and proof of concepts are important) but it does mean you should be practised at refactoring code and not simply slap poor fixes onto code that doesn't cleanly solve a problem in the first place.

Read more...

Method names in Objective-C

Compared to other languages, method names in Objective-C are weird. They're long, they're wordy, they include names for the parameters and they seem to repeat information you can get elsewhere. Despite these apparent negatives, Objective-C method naming can save you time and effort. I'll show you how methods are named so that you can predict them without documentation and understand how methods work and how they use their parameters from their names alone.

Introduction: Objective-C is an ugly duckling

Along with square-brackets and its largely Apple-exclusive nature, method names are one of the most commonly decried parts of Objective-C. I've seen them criticized for being:

  • Long and wordy
  • Repetitious or redundant
  • Filled with names for each parameter
  • Camel-case

While every one of these points is true, none of them is really a negative — although camel-case is a subjective, aesthetic point and I'll ignore it since I'll only consider the structural aspects of method naming conventions in this post.

Objective-C methods names are some of the most predictable, regular, self-descriptive methods in any C-derivative language — and it is these points that allow it to be so. Of course, these benefits are lost unless you know the conventions well enough to understand and predict them.

Background: naming conventions in other C-like languages

To help you understand the reasoning behind Objective-C's method names, I'll start by describing how methods and functions are named in C. I'm starting with C because Objective-C's method naming is, in some respects, an extension of C's naming style, adapted to overcome the limitations.

Standard C's naming style

Yes, Standard C does have some implicit naming conventions. Many standard C functions are composed of three parts:

  1. An indication of the data type acted upon
  2. The action
  3. A description of the secondary object

We can see examples of these in these functions:

  • sscanf - "s" (acts upon a char *), "scan" (extract character data from the string), "f" (format string is the secondary object)
  • fprintf - "f" (acts upon a FILE), "print" (outputs character data to the file), "f" (format string is the secondary object)
  • strlen - "str" (acts upon a char *), "len" (compute the length). No secondary object.
  • fesetround - "fe" (acts upon the "floating point environment"), "set" (changes a state value), "round" (a new rounding value is the secondary object).
Standard C's naming style fails

For these methods, this style works well. The problem is that components are so short (often single letters) that it is difficult to know for certain to what they refer. Many of the methods in math.h show these limitations:

  • lround - "l" (no longer an "acts upon", this first part now indicates "returns a long"), "round" (round to the nearest integer). No description of the primary parameter — you are expected to assume a double.
  • acosl - The "l" in this case is the primary parameter and means long double whereas it meant long in the lround method above. The "a" here is not a prefix, it is part of the action component.

This is where naming styles in C break down — while math.h does have naming conventions, they are all its own. You can learn the tricks of math.h but they are unique to that library, not a standard that applies to all functions.

Beyond these issues C, suffers from a broader lack of adherence to any convention, let alone a consistent one. Most functions are really just a 4 to 6 character description of the action performed. While this may be all that is required at a technical level, it makes it almost impossible to know how to use functions like system, raise, atexit or even malloc for the first time without reading the documentation.

Other languages

Few other languages have a distinct approach to method structure. The overriding convention in the main languages I use (C++, C#, Java) is simply a short verb plus possible modifier.

Some languages do have their own aesthetics (for example, the C++ Standard Library uses terse underscore delimited words) but this doesn't represent a structural convention.

The reason why these languages have abandoned the three part style of Standard C functions is that:

  1. The data type acted upon is now the object upon which the method is invoked, removing the need to explain this part.
  2. Parameter overloading means that a description of any parameter needs to be vague (since the parameter itself may be used inconsistently).

So methods end up being little more than a verb plus an optional modifier term.

The result is that methods with subtle actions or that use their parameters in specific ways can only be used by thoroughly examining the documentation.

Method naming conventions in Objective-C

Objective-C aims to be substantially more self-documenting than its peers. The intent is that all methods in all classes should be able to follow the same set of rules so that subtleties of behavior are easy to see and understand — even when you are new to the class.

This aim combines with the named parameters in Objective-C to produce methods which are quite distinct compared to other languages.

Given the lack of convention in other languages and the unusual nature of Objective-C's named parameters, it's no so surprising that method names in Objective-C are confronting to new Objective-C programmers.

Structure of an Objective-C method name

Objective-C methods are composed of a few different components. I'll list the components here, examples follow:

  1. If there is a return value, the method should begin with the property name of the return value (for accessor methods), or the class of the return value (for factory methods).
  2. A verb describing either an action that changes the state of the receiver or a secondary action the receiver may take. Methods that don't result in a change of state to the receiver often omit this part.
  3. A noun if the first verb acts on a direct object (for example a property of the receiver) and that property is not explicit in the name of the first parameter.
  4. If the primary parameter is an indirect object to the main verb of the method, then a preposition (i.e. "by", "with", "from") is used. This preposition partly serves to indicate the manner in which the parameter is used but mostly serves to make the sentence more legible.
  5. If a preposition was used and the first verb doesn't apply to the primary parameter or isn't present then another verb describing direct action involving the primary parameter may be used.
  6. A noun description (often a class or class-like noun) of the primary parameter, if this is not explicit in one of the verbs.
  7. Subsequent parameter names are noun descriptions of those parameters. Prepositions, conjunctions or secondary verbs may precede the name of a subsequent parameter but only where the subsequent parameter is of critical importance to the method. These extra terms are a way to highlight importance of secondary parameters. In some rarer cases secondary parameter names may be a preposition without a noun to indicate a source or destination.

In addition, an Objective-C method should be maximally readable — its reading should flow like a sentence and abbreviations should be avoided except where they are universally known (and even then, abbreviations to syllables rather than single letters are preferred).

That's a lot to consider. Fortunately, most components are only relevant to specific kinds of method.

Applying the naming convention to property accessors
length

This method is shows the typical form of a getter method for a property or calculated value. Only the first component of the method name applies.

The biggest point to note with respect to other languages is that getter methods don't use the verb "get" because no explicit action or state change is required to extract this property (implicit actions or actions taken for internal reasons should not be communicated through the method name).

encodedLength

This method shows a variant length method where a modifier is used to describe the length. We put the modifier before the property name because a structure like lengthWhenEncoded gets too close to lengthForEncoding: which would be used if the encoding was passed in as a parameter.

sharedApplication

Singleton accessors (like this accessor for the global UIApplication object) and other global data accessors take exactly the form as instance accessors. A description of the return value ("Application" in this case) plus an adjective to disambiguate it (in this case, disambiguation is required because a class name on its own is expected to be a factory method — see below). The term "shared" is used by convention to identify singletons.

doubleValue

This method has the same structure as the previous method but shows how the returned class is sometimes the modifier when used in conjunction with an abstract property like "value".

isEditable

This method is actually an exception to the conventional rules. The verb "is" shouldn't be there — verbs are normally reserved for describing state change or secondary action.

I guess that this style for accessors that return a BOOL developed to make the method read more like a sentence. You could also argue that "is" is a passive verb so it isn't indicating an action.

setLength:

The setter method is not composed in the same way as the getter. With no return value, the first part is a verb describing the action: "set".

The second part, "Length" may be considered to the direct object of the verb component (i.e. the internal property). In this case, it is also the name of the first parameter. Since they communicate the same information, only one is used.

Setter methods with prepositions before the first parameter like setValueUsingDouble: and setValueUsingNumber: are rarely used, even though they may seem like a good way to unambiguously set a property like "value" using different data types. Instead, the property itself is normally give a different name (i.e. setDoubleValue: or setNumberValue:). In this way, there is only ever one setter for a given property (although properties may contain dependencies).

Applying the naming convention to factory methods
string

This NSString method returns an empty string. It takes exactly the same format as a getter method, except that you invoke it on a class object, not an instance and it doesn't include a property name.

It may seem like this method is providing redundant information — we already know that a factory method for a class will return an instance of the same class — but identifying the return type here has two purposes:

  • factory method are identified precisely because they start with the class' name
  • it maintains consistency (always describe the return value when it is the purpose of the method)

A quick follow up to that second point though: the return value only needs to be described when it is the purpose of the method. BOOL values returned as an error indicator and other cases where the return value is a secondary effect (like autorelease which returns the receiver) do not need to describe the return value.

stringWithString:

The parameter here is named "String", indicating that it is an instance of NSString with no other constraints. The correct way to read this method is that it creates a new string in the simplest way possible from its string parameter — i.e. a copy of the string.

The preposition here is of little semantic purpose except to make the method name read like a sentence. The choice of preposition is simply: whatever is most appropriate if you read it like a sentence. For this reason class factory methods normally use "With" but instance factory methods normally use "By" because it implies some involvement of the receivers data (like stringByAppendingString:).

The NSArray method isEqualToArray shows a state interrogation with a preposition but again, the preposition is chosen simply to make the method name read like a sentence.

Applying the naming convention to action methods
release

This is an example of a simple action method: a verb describing how the method changes state or performs secondary actions.

addObject:

Again, a very simple method: verb plus a noun describing the first parameter (any "Object").

addObserver:forKeyPath:options:context:

The important addition to see here is the use of the preposition "for" in front of the second parameter. Yes, "KeyPath" is the indirect object of the method's verb "add" but the real purpose here is to highlight the importance of this parameter — pointing out that this parameter is more important than parameters which follow.

To explain this, consider that the method is not addObject:forKeyPath:usingOptions:andContext: — the options and context are really peripheral parameters whereas keyPath is an important consideration, despite being the second parameter.

This method can be compared to the very similar NSNotificationCenter method addObserver:selector:name:object:. In the case of the NSNotificationCenter method, name: is the corresponding parameter to forKeyPath: and yet no preposition is used (it is not forName:). This reflects the fact that the name parameter is optional (can be nil).

However you should not infer that lack of preposition means "optional" — far from it. Instead, the correct meaning is preposition means more important than other secondary parameters. The selector: parameter of the addObserver:selector:name:object: method is mandatory but is given no special status in the method. It is necessary for routing the notification but much of the time will simply reflect the notifications it observes (i.e. @selector(windowWillCloseNotification:)).

A small exception: delegate methods
windowDidChangeScreen:

This method begins with the name of a class but it is not a factory method nor a method which returns a mutated version of the receiver. It is actually a delegate method and delegate methods don't really follow any of the conventions.

If it were following the conventional standard its name would be receiveWindowDidChangeScreenNotification:. You could argue that delegate methods are passive — the delegate isn't being asked to perform an action, it is being told that something else performed an action — so omitting a verb is permissible. For my part, the break with convention makes me sad inside.

Further confusing things, the first parameter of the delegate method is rarely identified by the closest noun. Instead the first parameter is either the object sending the notification or it is a notification object (which will contain the sender). In the example above, the closest noun is "screen" but the first parameter is an NSNotification. In the case of applicationOpenUntitledFile: the closest noun is "File" but the parameter is the NSApplication object that sent the message.

Summary

In describing method formats, I've repeated myself quite a few times. The reality is that Objective-C uses one method naming convention almost everywhere.

Objective-C method names are very regular. So regular that you should be able to predict the names for methods without checking the documentation — start typing the method name as you guess it, then autocomplete. More than simply predicting the name, you can normally predict how parameters are used, so again you avoid documentation and know what you need.

Looking at the criticisms levelled at Objective-C method names that I listed at the start:

Long and wordy

Yes, Objective-C methods are made to read like sentences. They contain prepositions (something almost never seen in other languages), they contain type of the return parameter, they use full words instead of abbreviations.

The purpose is to make the method as quick to read as possible.

This is a good trade to make since you will read a method many times but only type it once (with code completion, less than once).

Xcode will suggest code completion automatically. Hit return at any time to pick the completion it offers. Hit the Code Sense Completion key (F5 by default) and it will present a popup list of matching options. Control-/ will step through the parameters so you can fill them in.
Repetitious or redundant

While methods like +[UIApplication sharedApplication] may seem redundant, the reality is that +[UIApplication shared] would have a different meaning (it would be an accessor for the static class property named "shared") and +[UIApplication singleton] by omitting a class name fails to communicate that the method also works as a factory method on the first invocation — repeating the class name has meaning, it is not redundant.

Filled with names for each parameter

Yes they are but these names makes it much easier to determine what each parameter is and allows metadata like importance to be conveyed.

Camel-case

Yes. The choice over underscore delimited words is largely aesthetic. Although the choice over Pascal-case (same as camel-case but where the first letter of the first word is uppercase not lowercase) is because uppercase initial letters are reserved for names with global scope — like class names, function names and global constants.

Conclusion

Few other languages have conventions that are as rigourously applied as those in Objective-C. Conventions are annoying to learn — as they may seem arbitrary and unnecessary at first glance — but once learned, they are regular and predictable with few surprises. When trying to get the computer to obey, that's good.

Further reading:

Read more...

Base64 encoding options on the Mac and iPhone

On Unix platforms, a common approach for Base64 encoding is to use libcrypto (the OpenSSL library). However, like most C libraries, you need to wrap it to integrate with Objective-C data types (like NSData and NSString) and it isn't available on the iPhone. I'll show you how to handle base64 encoding/decoding with OpenSSL and without so you can handle the Mac and iPhone equally.

Introduction

Base64 is an encoding for transferring binary data in 7-bit text. Originally used in email, it is also used for binary encoding data in HTML files. Another common use for Base64 is in HTTP Basic Access Authentication where it is used to transfer login details (which might not be printable characters).

The key library for handling Base64 on the Mac is normally libcrypto (the OpenSSL library), so it's a little disappointing that libcrypto isn't available on the iPhone.

Using OpenSSL

Via the command line

On the Mac, you can handle simple encoding tasks like base64 encoding with OpenSSL on the command line:

echo "Base64 encode this text." | openssl enc -base64

gives the encoding result:

QmFzZTY0IGVuY29kZSB0aGlzIHRleHQuCg==

The reverse is handled in the following manner:

echo "QmFzZTY0IGVuY29kZSB0aGlzIHRleHQuCg==" | openssl enc -d -base64

giving

Base64 encode this text.
In code

As you'd expect, doing the same work in code takes a little more typing. First, we're using a library, so we need to include it (in your Project's Build Settings under Other Linker Flags add the flag -lcrypto). Once that's done, you should be able to use the following method in a category on NSData:

#include <openssl/bio.h>
#include <openssl/evp.h>

- (NSString *)base64EncodedString
{
    // Construct an OpenSSL context
    BIO *context = BIO_new(BIO_s_mem());

    // Tell the context to encode base64
    BIO *command = BIO_new(BIO_f_base64());
    context = BIO_push(command, context);

    // Encode all the data
    BIO_write(context, [self bytes], [self length]);
    BIO_flush(context);

    // Get the data out of the context
    char *outputBuffer;
    long outputLength = BIO_get_mem_data(context, &outputBuffer);
    NSString *encodedString = [NSString
        stringWithCString:outputBuffer
        length:outputLength];

    BIO_free_all(context);

    return encodedString;
}

To handle a Base64 encode.

By default, encodedString will have newlines every 64 characters. If needed, you can disable the inclusion of newlines by adding the following line before the BIO_write:

BIO_set_flags(context, BIO_FLAGS_BASE64_NO_NL);

Tthe "BIO" system (I think it stands for buffered I/O) is not very symmetric so the code for decoding is quite different:

+ (NSData *)dataByDase64DecodingString:(NSString *)decode
{
    decode = [decode stringByAppendingString:@"\n"];
    NSData *data = [decode dataUsingEncoding:NSASCIIStringEncoding];
    
    // Construct an OpenSSL context
    BIO *command = BIO_new(BIO_f_base64());
    BIO *context = BIO_new_mem_buf((void *)[data bytes], [data length]);
        
    // Tell the context to encode base64
    context = BIO_push(command, context);

    // Encode all the data
    NSMutableData *outputData = [NSMutableData alloc];
    
    #define BUFFSIZE 256
    int len;
    char inbuf[BUFFSIZE];
    while ((len = BIO_read(context, inbuf, BUFFSIZE)) > 0)
    {
        [outputData appendBytes:inbuf length:len];
    }

    BIO_free_all(context);
    [data self]; // extend GC lifetime of data to here

    return outputData;
}

An interesting point to note at the top of this function: I add an extra newline to the start of the string. This is because if you have not disabled newlines and the string does not contain at least 1 newline, BIO_read will fail.

Handling Base64 on the iPhone

Using libcrypto isn't possible by default on the iPhone — the library isn't there. You could probably build libcrypto.a and link it statically against your app but that can be difficult to set up and would require that you notify Apple that your app contains encryption.

Normally, it is better to avoid libcrypto on the iPhone. The other functions that libcrypto handles can be found elsewhere:

  • md5 — use the CommonCrypto implementation CC_MD5
  • sha — use the CommonCrypto implementation CC_SHA
  • Public/Private Key Encryption/Decryption — use the SecKeyEncrypt/SecKeyDecrypt functions in the Security framework

You can find the documentation for the Security Framework by performing a standard Xcode API lookup. For some reason though, the CommonCrypto functions only appear in a full-text search.

The Base64 functionality of OpenSSL doesn't have an accessible equivalent on the iPhone, even though NSURLConnection, CFHTTPMessageRef and WebKit must all have access to an implementation — whatever they use is not accessible.

Encoding Base64

Fortunately, Base64 is a fairly simple encoding. At its heart, it looks like this:

static unsigned char base64EncodeLookup[65] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

//
// Inner loop: turn 3 bytes into 4 base64 characters
//
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
    | ((inputBuffer[i + 1] & 0xF0) >> 4)];
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
    | ((inputBuffer[i + 2] & 0xC0) >> 6)];
outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];

This might be a little ugly to look at if you're not use to seeing bitmasks and bitshifts but it is only a couple lines. It does little more than the comment states: it turns 3 bytes into 4 chars, with the specific chars specified by the base64EncodeLookup mapping.

Of course, while this code handles the center of the main loop, there's almost a hundred lines total in the complete implementation that I wrote.

As part of keeping the function optimal, I wanted to keep the conditionals out of the inner loop (making vectorizing easier). I succeeded and there are no conditionals in the inner loop but this means that there are a few tail conditions to handle in the epilogue.

I also wanted to calculate the exact size that would be required for the output buffer, so it can be allocated once with no waste, but this too occupies a few lines worth of space.

Decoding Base64

Decoding works similarly to encoding, except that in decoding we are reducing 4 characters down to 3 bytes instead of vice versa:

//
// Store the 6 bits from each of the 4 characters as 3 bytes
//
outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);
outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);
outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];

More interesting than the code in this case is the lookup table that each of these accumulated bytes passes through before being used here:

//
// Definition for "masked-out" areas of the base64DecodeLookup mapping
//
#define xx 65

//
// Mapping from ASCII character to 6 bit pattern.
//
static unsigned char base64DecodeLookup[256] =
{
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63, 
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, 
    xx,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx, 
    xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
};

The "xx"s in this table are just a #define of 65 (i.e. outside the valid range of Base64) but they provide an interesting visual representation of the 6-bits that each Base64 character can occupy within the 8-bit byte.

I was unable to remove all of the conditionals from the inner loop of the decode side and keep the "skip over invalid characters" requirement.

This "skip over invalid characters" stage (where characters are accumulated until 4 valid characters are found) is handled by the following loop (which immediately preceeds the previous "store the 6 bits from each of the 4 characters as 3 bytes" code):

//
// Accumulate 4 valid characters (ignore everything else)
//
unsigned char accumulated[BASE64_UNIT_SIZE];
size_t accumulateIndex = 0;
while (i < length)
{
    unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
    if (decode != xx)
    {
        accumulated[accumulateIndex] = decode;
        accumulateIndex++;
        
        if (accumulateIndex == BASE64_UNIT_SIZE)
        {
            break;
        }
    }
}

This is the only part which makes the decode stage sub-optimal. If you had Base64 input data with no newlines and no other characters requiring skipping, I think you could remove this section entirely so that the inner loop of the decode function could be vectorizable.

Conclusion

Download the NSData+Base64 class and header (4kB).

In this post, I've shown you how to use the default command-line and library options for Base64 handling on Mac OS X. I've also shown you the approach I use for Base64 encoding and decoding on the iPhone.

The libcrypto libraries (when available) are not as tight and simple as custom code for the task but do have the advantage that the pipeline for feeding data into them is more configurable.

I'm certainly not the only one to present C libraries for Base64 encoding that will work on the iPhone but the approach I've used should be efficient (especially the internal implementations in the C-functions) and it should drop into a Cocoa project on the iPhone very easily.

Read more...

Simple methods for date formatting and transcoding

There is no single-line method for converting between formatting date strings and date objects in Cocoa — the API opts for flexibility rather than simplicity. Unfortunately, this combines with documentation that omits, misdirects and occasionally misinforms, making NSDateFormatter one of the more confusing classes for new Cocoa programmers. In this post, I'll try to address some of the documentation issues and I'll present some methods that will turn NSDate into a formatted string or convert between date strings in a single method.

Default, locale-based date formatting

Before I get into date formatting strings (which is the real purpose of this post) I will quickly show you how to get a string from an NSDate:

NSDate *date = [NSDate date];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
NSString *dateString = [dateFormatter stringFromDate:date];

This code formats the string according to the user's preferences set in the International General Settings (iPhone) or System Preferences (Mac OS X).

Personally, I think this is verbose for such a common activity and normally use a category method on NSDate to reduce it:

@implementation NSDate (FormattedStrings)
- (NSString *)dateStringWithStyle:(NSDateFormatterStyle)style
{
    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
    [dateFormatter setDateStyle:style];
    return [dateFormatter stringFromDate:self];
}
@end

This reduces the first code sample to:

 NSString *dateString = [[NSDate date] dateStringWithStyle:NSDateFormatterLongStyle];

If you need time strings instead of date strings, create a timeStringWithStyle: method by replacing the setDateStyle: invocation with setTimeStyle:.

I have read rants by other Objective-C programmers who hate seeing projects with hundreds of small categories for every little task.

Frankly, I've never understood the objection. In fact, I think lots of small categories used to choose the settings you prefer on top of common interfaces is essential for establishing consistent aesthetics for your program — your entire program will have the same style and you can easily update the aesthetic for the whole program by editing a single location.

An example would be to replace this dateStringWithStyle: method with a dateStringWithProjectStyle method that returns the appropriately configured string for use throughout your program. One of your projects might use NSDateFormatterLongStyle and the next might use a totally customized format (as I'll describe in the next sections) but you as a programmer can still invoke dateStringWithProjectStyle everywhere you need a string from an NSDate.

Date formatting documentation issues

At its heart, NSDateFormatter is very simple to use and yet it repeatedly baffles new users. I don't think this is really the fault of the API as much as the history behind it and the effect that it has had on the documentation.

Despite NSDateFormatterBehavior10_4 being the only date formatting you should ever use and the only style that should exist in the documentation, Apple's documentation has the following quirks:

  1. The actual syntax for NSDateFormatterBehavior10_4 is never given in the documentation and you can easily miss the links to Unicode Standard (tr35) which describe it.
  2. A majority of the pages in the date formatting documentation seem concerned with the old NSDateFormatterBehavior10_0 style formatter behavior even though this is functionally deprecated.
  3. The documentation for defaultFormatterBehavior claims NSDateFormatterBehavior10_0 is the default style but it is actually NSDateFormatterBehavior10_4 in Leopard and iPhoneSDK2.0.

Then, if you've been skimming through the documentation getting confused by the different styles, you may overlook one line at the top of the NSDateFormatter API reference page:

iPhone OS Note: iPhone OS supports only the modern 10.4+ behavior. 10.0-style methods and format strings are not available on iPhone OS.

All that documentation in the iPhone SDK concerned with the old NSDateFormatterBehavior10_0 style is completely meaningless — you can't use NSDateFormatterBehavior10_0 at all on the iPhone.

Adding to the iPhone frustration, NSDateFormatterBehavior10_0 will work in the simulator, causing headaches when code suddenly stops working on the device.

On Mac OS X, even though you can use NSDateFormatterBehavior10_0, it is deprecated for all practical purposes so you probably shouldn't. Annoyingly, since the documentation still claims NSDateFormatterBehavior10_0 is the default, you should explicitly set the formatter behavior to NSDateFormatterBehavior10_4 to remain safe — at least until the documented default is updated to formally match the actual default.

I don't mean to be cruel to Apple — documentation is difficult, time consuming and annoying — but I suspect these quirks in the documentation and behavior are responsible for a lot of confusion.

Date formatting syntax

Setting a date formatting string looks like this:

NSDate *date = [NSDate date];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:@"dd MMM, yyyy"];
NSString *dateString = [dateFormatter stringFromDate:date];

This will create a string of the format "26 May, 2009". The arrangement of data in this string is determined by the format string passed to the setDateFormat: method.

A quick summary of the date formatting options useable in this format string:

CharacterMatches/OutputsMultiples
yYear1, 2 or 4 'y's will show the value, 2 digit zero-padded value or 4 digit zero-padded value respectively
MMonth1, 2, 3, 4 or 5 'M's will show the value, 2 digit zero-padded value, short name, long name or initial letter months
dDay of Month1 or 2 'd's will show the value or 2 digit zero-padded value representation respectively.
eWeekday1, 2, 3, 4 or 5 'e's will show the value weekday number, 2 digit zero-padded value weekday number, short name, long name or initial letter respectively. Weekday numbers starts on Monday. Use uppercase 'E' for weekday numbers starting on Sunday.
aAM or PMNo repeat supported
hHour1 or 2 'h's will show the value or 2 digit zero-padded value representation respectively. Use uppercase for 24 hour time.
mMinute1 or 2 'm's will show the value or 2 digit zero-padded value representation respectively.
sSecond1 or 2 's's will show the value or 2 digit zero-padded value representation respectively.
zTimezone1, 2, 3 or 4 'z's will show short acronym, short name, long acronym, long name respectively. Use uppercase to show GMT offset instead of name — 1 or 2 digit zero-padded values shows GMT or RFC 822 respectively.

Case is important — using the wrong case can cause parsing to fail. Use lowercase by default for all values except Month.

Alphabetic and numeric characters should be enclosed in single quotes (asterisk character) if you want them to pass through the parser as literal characters. A double asterisk will pass through as a single asterisk (self escaping). Most other punctuation and spaces will go through as normal except backslash which works like a normal C-string escape character to handle tabs, newlines and other special characters.

For the complete specification, including the more obscure options that I haven't bothered to list, see Unicode Standard (tr35).

Date string transcoding

The date formatting options can also be used to parse strings. With parsing and output formatting, we can create a date string transcoder method in a category on NSDateFormatter:

+ (NSString *)dateStringFromString:(NSString *)sourceString
    sourceFormat:(NSString *)sourceFormat
    destinationFormat:(NSString *)destinationFormat
{
    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
    [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
    [dateFormatter setDateFormat:sourceFormat];
    NSDate *date = [dateFormatter dateFromString:sourceString];
    [dateFormatter setDateFormat:destinationFormat];
    return [dateFormatter stringFromDate:date];
}

We can use this method to convert one date string (for example "2007-08-11T19:30:00Z") into another ("7:30:00PM on August 11, 2007") in the following manner:

NSString *inputDateString = @"2007-08-11T19:30:00Z";
NSString *outputDateString = [NSDateFormatter
    dateStringFromString:inputDateString
    sourceFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"
    destinationFormat:@"h:mm:ssa 'on' MMMM d, yyyy"];

Calendar stuff

The NSDateFormatter class is just for parsing and formatting strings. You shouldn't use it to build dates from their components or to decompose dates into components. For that task, use NSCalendar. It's a little outside the scope of this post but since I know it will come up, here's how to set an NSDate to the 26th of May, 2009 using NSCalendar:

NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
[components setDay:26];
[components setMonth:5];
[components setYear:2009];
NSCalendar *gregorian =
    [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDate *date = [gregorian dateFromComponents:components];

To get the components from a date, use:

unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
NSDate *date = [NSDate date];
NSCalendar *gregorian =
    [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *components = [gregorian components:unitFlags fromDate:date];

Conclusion

As I've said a few times now, the actual API for date formatting in Cocoa is simple. The only reason why I consider it a topic worthy of a post is that I still see at least one question a week on StackOverflow and other forums asking why NSDateFormatter is failing in their code and the answer is normally because their code confuses the formatting behaviors, uses the wrong format specifiers or has otherwise misunderstood the required steps.

I hope what I've presented clears up these issues. Date formatting should be simple enough that you can write it once and never worry about it again.

Read more...

Intercepting status bar touches on the iPhone

You can configure your iPhone applications so that a touch in the status bar will scroll a UIScrollView to the top. I'll show you how you can intercept this touch event to use status bar touches for other purposes. The sample application will show a hidden drawer that slides out from the status bar when you tap it.

Touches in the status bar

A lesser known user-interface feature on the iPhone is that touches in the status bar will usually scroll the main UIScrollView to the top, providing a quick way to scroll to the top of long documents.

This will work in your application when exactly one UIScrollView returns YES for the scrollsToTop property (YES is the default). If more than one UIScrollView returns YES for this property (or the UIScrollView's delegate returns NO from scrollViewWillScrollToTop:) the scroll to top functionality will be disabled.

That's the ordinary functionality but how do we achieve different functionality?

The HiddenDrawer sample appliction

hidden_drawer_screenshots.png

These screenshots show the HiddenDrawer sample application. When the status bar is tapped on the left, the hidden drawer animates out from under the status bar, resulting in the state shown on the right.

Stealing status bar touch events

The trickiest part of the sample application is detecting a touch in the status bar.

By implementing a custom setContentOffset:animated: method on a UITableView and setting a breakpoint in that method, you can see in the debugger stack that the UIApplication sendEvent: method is invoked for status bar touches, so that's where we'll begin.

CustomApplication

Overriding UIApplication is extremely rare so I'll explain how to make it work. Once you create the subclass of UIApplication you need to tell the program to use that subclass. In Cocoa Senior (Mac OS X) you specify application subclasses in the Info.plist file. In Cocoa Touch, you specify custom application subclasses by name in the UIApplicationMain function in the main.m file:

int retVal = UIApplicationMain(argc, argv, @"CustomApplication", nil);
sendEvent:

The only method override we need in CustomApplication is sendEvent:. The difficult part is then working out from the UIEvent which events are status bar touch events — unfortunately, the allTouches method returns an empty array for status bar touches.

Instead, we delve into the secret GSEvent.

I previously accessed GSEvent in my post Synthesizing a touch event on the iPhone. In that post, I created a PublicEvent class and a fake GSEventProxy class to access the required fields. This time, I'm going to use a different approach and jump straight to the data I need.

- (void)sendEvent:(UIEvent *)anEvent
{
    #define GS_EVENT_TYPE_OFFSET 2
    #define GS_EVENT_X_OFFSET 6
    #define GS_EVENT_Y_OFFSET 7
    #define STATUS_BAR_TOUCH_DOWN 1015
    
    // Traverse from the UIEvent to the GSEvent to the type
    int *eventMemory = (int *)[anEvent performSelector:@selector(_gsEvent)];
    int eventType = eventMemory[GS_EVENT_TYPE_OFFSET];

    // Look for status bar touches by event type
    if (eventType == STATUS_BAR_TOUCH_DOWN)
    {
        // The next 6 lines aren't essential but if you want to know where the
       // touch coordinates live, here they are: 
        int xMemory = eventMemory[GS_EVENT_X_OFFSET];
        int yMemory = eventMemory[GS_EVENT_Y_OFFSET];

        typedef union {int intValue; float floatValue;} Int2Float;
        float x = ((Int2Float)xMemory).floatValue;
        float y = ((Int2Float)yMemory).floatValue;

        NSLog(@"Status bar down at %f, %f", x, y);
        
        // Send a message to the delegate to handle the action
        [(HiddenDrawerAppDelegate *)self.delegate toggleDrawer];
    }
    else
    {
        [super sendEvent:anEvent];
    }
}

You may be curious to know where the OFFSET values come from. The answer is that I spent a while staring at the raw memory values in the GSEvent object while deliberately causing status bar and other touch events — nothing fancier than that. It's tricky and unreliable. If it works at all in iPhoneSDK3.0, it'll be pure luck.

I also use a union here. This is because I step through memory as ints and in C, a basic cast from int to float causes a value conversion (I want a reinterpret, not a value conversion).

I also chose to suppress status bar touch events going through to the UITableView by the normal route. If you want to re-enable this behavior, you can take the [super sendEvent:anEvent]; line out of the else block and put it in the main method body.

Animating the drawer

The sendEvent: implementation above invokes the toggleDrawer method on the application's delegate.

All that's required is to animate the drawer's view in and push the table's view down:

drawerController = [[HiddenDrawerViewController alloc] init];

// Position the drawer below the status bar
CGRect drawerFrame = drawerController.view.frame;
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
drawerFrame.origin.x = statusBarFrame.origin.x;
drawerFrame.size.width = statusBarFrame.size.width;
drawerFrame.origin.y = statusBarFrame.origin.y + statusBarFrame.size.height;

// For the animation, move the drawer up by its own height.
drawerFrame.origin.y -= drawerFrame.size.height;

// Place the drawer and add it to the window
drawerController.view.frame = drawerFrame;
[window addSubview:drawerController.view];

// Start the animation
[UIView beginAnimations:nil context:nil];

// Move the table down
CGRect tableFrame = viewController.view.frame;
tableFrame.origin.y += drawerFrame.size.height;
viewController.view.frame = tableFrame;

// Move the drawer down
drawerFrame.origin.y += drawerFrame.size.height;
drawerController.view.frame = drawerFrame;

// Commit the animation
[UIView commitAnimations];

If you download the whole project, you'll see that there's also an animate up and remove branch that gets run if the drawerController already exists.

Conclusion

You can download the HiddenDrawer sample project (30kB) to see the whole application in action.

A hidden drawer under the status bar isn't necessarily something that every iPhone application should have but the obscure, secretive nature of it appeals to me.

The approach of determining which UIEvent we want by the type field in the GSEvent is a little precarious. Apple are free to change the structure of GSEvent at any time, which could cause your application to misbehave or crash so this type of code would need to be tested on each iPhone OS release to ensure that it still works.

Read more...