Speex On iPhone Explained Part II


*Update*
From part I I neglected to point out that you should un comment #define _USE_SSE in the config.h as mentioned below. This preproc directive will allow you to run on device. It was also mentioned that you could get more speed out of Speex if you #define FIXED_POINT instead of FLOATING_POINT. I have not verified this and Speex runs acceptable in my implementation without it but its worth mentioning.
*Update*

You have a lot of vocal audio data. Maybe it needs to be stored on an iPhone. Maybe it needs to glide effortlessly over the network like a slice of dental floss blowing in the wind. Whatever the case, you need a good compressor and Speex is a great solution. Hi, I’m Cliff. You’re here because you’re looking for an answer to your audio compression needs. I’m here to deliver the secrets to decompressing audio with the Speex codec. That, for what it’s worth, is the only reason I’m still hanging around here. In any other event you’d probably find me on South Street sharing a soda with a cat. I digress . . .

In part I of this series I explained how to get Speex to compile. Today we’ll try to import the OGG container format into our project and move onto Speex decompression. Because not everyone may be aware, a brief explanation on codecs and containers is in order. Audio encoding is typically made of two distinct pieces. You would usually have a container format and an encoding. The audio container holds the meta data, or descriptive information, for the actual audio file. This meta or descriptive information includes things like how many channels are in the audio data, what sample rate it is recorded at, and the endianness (not Indianness) of the audio data. There are other potential data held in the container format depending on the type of encoding you use. Finally, the descriptive (meta) data will have the location (offset) of the actual audio data in the file. The encoding is the actual raw audio data that is to be delivered directly to the output device or speakers. The encoding can be a direct digital dump (that is the actual audio samples taken over time as the audio was recorded) or it can be a compressed variant of the raw samples. It’s important to note that the encoding and the container are not usually dependent upon one another. That mean you can mix and match Speex encoding with a wave container format just the same as you can put raw uncompressed samples in an OGG container. It’s just more common to find uncompressed data in a wave container and Speex compressed audio in an OGG container.

Let’s take a step back and try some TDD. Following best practices, we need to create a need for the Speex codec and the OGG container. I realize this is cart before the horse style since we’ve already imported Speex but bear with me as I’m doing this tutorial on my time off. Also up until now I’ve been completely out of the TDD habit for a while as I strive to work closely with others who are uncomfortable with the style. We start by creating a “Unit Test Bundle” target in the project. Create a new objective C class named “CCCSpeexDecoderTest” using the “New File…” dialog and do not choose (unselect) the “also create .h file” option. Include the following in your new Objective-C class file.

//
//  CCCSpeexDecoderTest.m
//  SpeexLib
//
//  Created by Clifton Craig on 11/13/10.
//  Copyright 2010 Craig Corporation. All rights reserved.
//
#include <SenTestingKit/SenTestingKit.h>

@interface CCCSpeexDecoderTest : SenTestCase
{
	NSString* wavFile;
	NSString* speexFile;
}
@end

@implementation CCCSpeexDecoderTest

-(void) setUp
{
	wavFile = [[NSBundle bundleForClass:[self class]] pathForResource:@"sample" ofType:@"wav"];
	speexFile = [[NSBundle bundleForClass:[self class]] pathForResource:@"sample" ofType:@"spx"];
}

-(void) testFirstTest
{
	STAssertNotNil(wavFile,@"A sample wav file is required to test speex decoding.");
	STAssertNotNil(speexFile,@"A sample speex file is required to test speex decoding.");
}

@end

Running this tells us that we’re going to need some speex data to operate on. (I’ve taken the liberty to generate a wav file using the “say” command and converted it to a Speex encoded file using the JSpeex API via Groovy. I’ll include both in a download of the project for this lesson.) Next we’ll create a structure to hold our unit tests and test resources. We will be following the “golden copy” testing pattern. You later learn that using the pattern here is rather fragile, however a more purist approach would take us through an exercise of re-writing the entire Speex project which is outside the scope of my tutorial. Using Finder, I created a “Tests” and a “Resources” folder under my src folder in my project. Drag/drop these folders into XCode to create the corresponding groups. Then drag/drop the sample wave and sample speex files (named “sample.wav” and “sample.spx” respectively) into the “Resources” group in XCode. Running the test will now pass.

We now work our way through creating the decoder. I’ll spare the individual steps in TDD as it would make this text overly verbose and I’ll try to summarize instead. We need an actual decoder instance which we’ll be importing. TDD suggests we import what we don’t have so add the import for a CCCSpeexDecoder type which does not exist. Build and fail. (The failure is important as it formalizes the class or feature you are about to add/change/delete.) We also need to be able to create this type and give it some audio to decode. It will also need a place to send the decoded audio data. I’m going to define an abstraction for providing/receiving the audio data so that we don’t necessarily need a file system so I’m adding a test to demonstrate/document the need for an audio source, a test to demonstrate/document the need for an audio sink, and one other test that formalizes how we plug these two abstractions into the decoder.

#import "CCCSpeexDecoder.h"

@interface CCCSpeexDecoderTest : SenTestCase <CCCSpeexAudioSource, CCCSpeexAudioSink>
{
	NSString* wavFile;
	NSString* speexFile;
	CCCSpeexDecoder *decoder;
}
@end

@implementation CCCSpeexDecoderTest

//...

-(void) testAudioSourceIsDefined
{
	id<CCCSpeexAudioSource> anAudioSource = self;
}

-(void) testAudioSinkIsDefined
{
	id<CCCSpeexAudioSink> anAudioSink = self;
}

-(void) testCanCreateDecoder
{
	[[CCCSpeexDecoder alloc] initWithAudioSource:self andAudioSink:self];
}

And this calls for the additional CCCSpeexDecoder class which defines the abstractions…

#import <Foundation/Foundation.h>

@protocol CCCSpeexAudioSource

@end

@protocol CCCSpeexAudioSink

@end

@interface CCCSpeexDecoder : NSObject {

}

- (id) initWithAudioSource:(id<CCCSpeexAudioSource>) anAudioSource andAudioSink:(id<CCCSpeexAudioSink>) anAudioSink;

@end

#import "CCCSpeexDecoder.h"

@implementation CCCSpeexDecoder

- (id) initWithAudioSource:(id<CCCSpeexAudioSource>) anAudioSource andAudioSink:(id<CCCSpeexAudioSink>) anAudioSink
{
	self = [super init];
	if (self != nil) {

	}
	return self;
}

@end

Now we go back and add one more test that explains what we’re after.

-(void) testCanDecode
{
	[decoder decodeAudio];
}

Build and fail so that we know to define the method.

-(void) decodeAudio
{
}

We now have defined the ability to decode audio. We have to set our expectation for this method. (Test first begins with declaring or expressing a need for a feature or function then setting an expectation for its behavior.) After invoking decodeAudio we would expect to have collected the decoded audio bytes somewhere. I’ll add a mutable data fieldin the test for this.

@interface CCCSpeexDecoderTest : SenTestCase <CCCSpeexAudioSource, CCCSpeexAudioSink>
{
	NSString* wavFile;
	NSString* speexFile;
	CCCSpeexDecoder *decoder;
	NSMutableData *decodedAudio;
}
@end

@implementation CCCSpeexDecoderTest

-(void) setUp
{
	wavFile = [[NSBundle bundleForClass:[self class]] pathForResource:@"sample" ofType:@"wav"];
	speexFile = [[NSBundle bundleForClass:[self class]] pathForResource:@"sample" ofType:@"spx"];
	decoder = [[CCCSpeexDecoder alloc] init];
	decodedAudio = [[NSMutableData alloc] init];
}

And we add a test to exercise the method and document/verify our expectation:

-(void) testDecodeAudioFillsDecodedAudio
{
	STAssertTrue([decodedAudio length] == 0, @"Should NOT have accumulated data");
	[decoder decodeAudio];
	STAssertTrue([decodedAudio length] > 0, @"Should have accumulated data");
}

Here’s the Oogly part. We are calling a method with no return value. We’ve defined an abstraction around collecting data (an audio sink) and we’ve made our test case adopt the protocol for this abstraction. The protocol defines no methods. The test calls for data to magically arrive in the mutable data field. Indirectly, our test is stating that given a source and a sink, when the decodeAudio message is sent we should have accumulated data in the sink. running the test fails because we haven’t added the functionality. We step into the decodeAudio implementation and fill in the simplest thing that works.

-(void) decodeAudio
{
	NSString *pretendData = @"pretendData";
	[audioSink audioWasDecoded:
		[NSData dataWithBytes:[pretendData cStringUsingEncoding:NSUTF8StringEncoding] length:[pretendData length]]
	 ];
}

You see we are talking to an audioSink object here. Because we don’t really have an audiosink object in scope (I just made it up b/c it felt right) we need to declare it.

@interface CCCSpeexDecoder : NSObject {
	id<CCCSpeexAudioSink> audioSink;
}

If we run we still won’t get satisfaction because we haven’t ensured that the audiosink given in the constructor is the one we talk to when we decode audio. So we revisit the init method.

- (id) initWithAudioSource:(id<CCCSpeexAudioSource>) anAudioSource andAudioSink:(id<CCCSpeexAudioSink>) anAudioSink
{
	self = [super init];
	if (self != nil) {
		audioSink = [anAudioSink retain];
	}
	return self;
}

We also need to release in our dealloc.

- (void) dealloc
{
	[audioSink release];
	[super dealloc];
}

Let’s be more specific. When decoding audio we will want to discover the meta data or attributes of the audio. This information is usually the first group of bytes in a file and it explains what the rest of the file contains. We’ll declare an expectation to receive a callback in our sink which contains the meta data in an easily navigable NSDictionary.

-(void) testDecodeAudioReturnsHeaderInfoToSink
{
	STAssertNil(headerInfo, @"We should start with no header info.");
	[decoder decodeAudio];
	STAssertNotNil(headerInfo, @"We should now have header info.");
}

and we need to add an NSDictionary field to our test to record the header info.

@interface CCCSpeexDecoderTest : SenTestCase <CCCSpeexAudioSource, CCCSpeexAudioSink>
{
        //Other fields...
	NSDictionary *headerInfo;
}
@end

we add the simplest thing that will work.

-(void) decodeAudio
{
	NSString *pretendData = @"pretendData";
	[audioSink headerWasDecoded:[NSDictionary dictionary]];
	[audioSink audioWasDecoded:
		[NSData dataWithBytes:[pretendData cStringUsingEncoding:NSUTF8StringEncoding] length:[pretendData length]]
	 ];
}

…And this calls for an additional method in our AudioSink protocol.

@protocol CCCSpeexAudioSink <NSObject>

-(void) audioWasDecoded:(NSData*) someDecodedAudio;
-(void) headerWasDecoded:(NSDictionary*) theAudioAttributes;
@end

Which bleed back into the test where we store the attibutes as our header info. Add the following to the test case.

-(void) headerWasDecoded:(NSDictionary*) theAudioAttributes
{
	headerInfo = theAudioAttributes;
}

Now we’ll look at individual attributes given to the sink during the parse. We set some expectations for numeric values mapped to specific keys in the header info.

-(void) testDecodeAudioHeaderInfoIncludesSpecificValues
{
	[decoder decodeAudio];
	NSNumber *value = [headerInfo valueForKey:@"sampleRate"];
	STAssertNotNil(value, @"Should have returned a number");
	value = [headerInfo valueForKey:@"frameSize"];
	STAssertNotNil(value, @"Should have returned a number");
	value = [headerInfo valueForKey:@"numberOfChannels"];
	STAssertNotNil(value, @"Should have returned a number");
	value = [headerInfo valueForKey:@"decodeBlockSize"];
	STAssertNotNil(value, @"Should have returned a number");
	value = [headerInfo valueForKey:@"framesPerPacket"];
	STAssertNotNil(value, @"Should have returned a number");
}

And as you’ll note a pattern here we should do some refactoring.

-(void) assertNumericValueInDictionary:(NSDictionary*)aDictionary atKey:(NSString*)aKey
{
	NSNumber *value = [headerInfo valueForKey:aKey];
	STAssertNotNil(value, @"Should have returned a number");
}

-(void) testDecodeAudioHeaderInfoIncludesSpecificValues
{
	[decoder decodeAudio];
	[self assertNumericValueInDictionary:headerInfo atKey:@"sampleRate"];
	[self assertNumericValueInDictionary:headerInfo atKey:@"frameSize"];
	[self assertNumericValueInDictionary:headerInfo atKey:@"numberOfChannels"];
	[self assertNumericValueInDictionary:headerInfo atKey:@"decodeBlockSize"];
	[self assertNumericValueInDictionary:headerInfo atKey:@"framesPerPacket"];
}

Because I forget the attributes of the file provided I’m going to use a discovery test technique. With this technique we use a dummy expected value in our assert and allow the assertion error message tell us what the actual value is. I wouldn’t do this in normal testing. It’s only because I already have working code that I’m plugging in and because this tutorial is getting wordy that I’m going to take the cheap way out.

-(void) assertIntValue:(int)anInt isInDictionary:(NSDictionary*)aDictionary atKey:(NSString*)aKey
{
	NSNumber *value = [headerInfo valueForKey:aKey];
	STAssertNotNil(value, @"Should have returned a number");
	STAssertEquals([value intValue], anInt, @"Integer value %i should exist for key %@", anInt, aKey);
}

-(void) testDecodeAudioHeaderInfoIncludesSpecificValues
{
	[decoder decodeAudio];
	[self assertIntValue:-999 isInDictionary:headerInfo atKey:@"sampleRate"];
	[self assertIntValue:-999 isInDictionary:headerInfo atKey:@"frameSize"];
	[self assertIntValue:-999 isInDictionary:headerInfo atKey:@"numberOfChannels"];
	[self assertIntValue:-999 isInDictionary:headerInfo atKey:@"decodeBlockSize"];
	[self assertIntValue:-999 isInDictionary:headerInfo atKey:@"framesPerPacket"];
}

Once we implement the actual parsing logic we will start to see the actual values reported in the assertion errors. (I am adapting existing working code rather than developing the code from test cases.) We will pull the values from the errors back into the asserts to make the test pass and document what our expectations actually are.

Now we need to actually start pulling audio from our audio source abstraction. Because we used protocols, our test can pose (using the self-shunt pattern) as the audio source and provide data for the decoder. We step into the decoder and start doing some actual parsing.

-(void) decodeHeader
{
	[audioSink headerWasDecoded:[NSDictionary dictionary]];
}

-(void) decodeAudio
{
	NSString *pretendData = @"pretendData";
	[self decodeHeader];
	[audioSink audioWasDecoded:
		[NSData dataWithBytes:[pretendData cStringUsingEncoding:NSUTF8StringEncoding] length:[pretendData length]]
	 ];
}

Importing OGG

At this point we have to import OGG for decoding the container so we can read the file meta data. Download and unpack libogg (not liboggz) from the Xiph.org download site.

We need to add the ogg header files to the header search path, so drag/drop the ogg folder from the include folder in the root of the unpacked directory into your XCode project. (/path/to/libogg-1.2.1/include/ogg) Choose to Copy the files from the dialog and select your static lib target before accepting the dialog. Delete the config_types.h.in and makefile.am and Makefile.in from this folder and group. (Also move them to trash.) Double click the project icon in the left tree pane and select the “Build” tab. Type “header search” in the search box at the top to narrow the options to the header search path. You need to add, “$(SRCROOT)” as one of your header search path values here. Create an XCode group for the ogg source code and drag/drop the “bitwise.c” and “framing.c” files from the unpacked libogg source folder. (/path/to/libogg-1.2.1/src).

At this point building unit test target should leave you with errors from the latest round of header info asserts which we will fix in the next part of the series. We have a fully configured project with access to both the speex and ogg encoding/decoding APIs which is exciting. In the next part of the series we will tackle calling into these APIs to decode the data. I’m going to upload my part II example project to my box account so it will be in the right and pane for your downloading pleasure. Until next time…

(Some of you will have noticed I accidentally published this post the other day before finishing it. This is why I’m publishing it half baked tonight. There’s alot here and a lot more to cover. Keep checking back for updates!)

Objective-C Gotchas


You’re working in Objective-C land trying to get a product out the door and into the Apple iTunes Store, right? (Don’t argue with me I’m just setting the stage.) You’re feeling the second cup of coffee seep into your bloodstream which creates a certain euphoric sensation as the last 3 times you mashed Cmd+B turned up no errors. Yes, that’s what’s happening in your copy of XCode right now. You then Cmd+Tilde to toggle the other XCode window active (Cmd+Tilde is a nifty Apple shortcut for switching active windows in the current app) and Cmd+B once again when a red flag on the play pops up in some code that had been just fine moments ago? What happened? Hi, I’m Cliff. You’re here because XCode got’cha and you’re not quite sure how/why/where. I’m here because I wanna list as many of these got’chas before I forget them.

Property accessor notation in Earlier SDKs
Here’s one weird gotcha that I just hit again for the first time. If you have a variable typed as a protocol and that protocol has a setter, which takes another protocol type defined then you may get an error when using dot notation in SDKs earlier than 3.0. That is a definition like this:

@protocol MyCoolAbstractType <NSObject>
-(void) setNetworkDataProvider:(id<MyNetworkDataProvider>)aNetworkDataProvider;
@end

…should be coded like this:

@protocol MyCoolAbstractType <NSObject>
@property (nonatomic, retain) id<MyNetworkDataProvider> networkDataProvider;
@end

…before you can do this:

id<MyCoolAbstractType> myObj = //create object from factory
myObj.networkDataProvider = [[MyConcreteNetworkDataProvider alloc] init];

Evidently the “Discover setter is a property” feature is something new Santa delivered with 3.0 and never told me about. Here I thought I had that toy from 2 years ago!

Unit Tests Can’t Be Signed
I added a unit test dependency to my “Application” target the other week in order to streamline my dev cycles. The idea was to ensure any changes I made to satisfy the integrated application bundle did not impact behaviors outlined in my test cases. (I use mini applications to perform my integration testing.) The problem here is that, even though this works well for simulator builds, an on-device build will fail as XCode attempts to sign your unit test target output. I haven’t discovered a work-around for this one yet so I’m gonna just punt and remove the test dependency from any targets meant to run on device.

I’ll trow up more as I find them…

Hard to test things


So I’d been thinking. Because I’m back into iPhone development and getting warmed up not only to ObjC issues and errors but also C++ oddities, I’m wondering how do you write tests for some of the more difficult things to capture? For instance, I’ve figured out how to capture some of the manual reference counting that’s required by CocoaTouch. (I assert that objects passed into other objects are properly retained and properly released when the object itself is released.) Still I can’t capture the more involved memory management problems. How do you assert an autorelease? What about dynamic memory allocation with pointers? I ended up with a single method that dynamically allocates for a pointer via malloc. I then changed it to use new with array notation.

void MySpecialObject::writeRequestToStream(CFStringRef aRequest, CFWriteStreamRef requestStream)
{
if(CFWriteStreamGetStatus(requestStream) == kCFStreamStatusNotOpen) CFWriteStreamOpen(requestStream);
UInt8* convertedString =(UInt8*)convertToCString(aRequest);
CFWriteStreamWrite(requestStream, convertedString, CFStringGetLength(aRequest));
free(convertedString);
}

It’s used in one spot so far and I’ve manually added the free without a prior failing test. I felt dirty. Assuming there were no call to free, how would you write a failing test for the code above? Is this just one of those things where you have to be extra careful? Maybe I should investigate the use of Velocity style code macros/templates that expand after keying special abbreviation similar to what we have in IntelliJ. I can imagine something like “cstr” expanding to:

char *myCStr = new char[size];
// use myCStr here
free(myCStr);

With the ability to tab through highlighting the variable name, declared size and commented insert code section. Any bright ideas?

AssertRunsInAnotherThread ?


**Update**
I’ve updated my example below after realizing I left out some important pieces…
**Update**

How do you assert that something runs in a different thread? Or more generically, how do you assert that something runs asynchronously? I need to do this in ObjC but also in Java. The scenario is as follows. I have a WhatzItz object instance stored in myWhatzItz. I tell myWhatzItz to doDisThing. I need to specify that myWhatzItz will doDisThing asynchronously. Experience tells the story that multi-threaded unit tests are dumb, complicated and wrong. So asking myWhatzItz to doDisThing then waiting or polling for completion of doDisThing is not what we want to do here. (It may be what you want to do but it’s not what I want. Since we’re on the same team and since I’m doing the writing you have to want what I want not what you want. I want you to want my wants… forget your wants… your wants are dumb anyhow!)

So how do we design myWhatzItz to doDisThing and doDisThing right? I’m going to suggest an interface… err prototcol. That is an abstraction for what we want to design. In unit testing we stay focused on one thing. All distractions are tossed behind abstractions. So after asking myWhatzItz to doDisThing I need to assert that it uses asynchronous behavior. That brings us a step back. I have to design a dependency on asynchronous behavior first. Right now you’re probably wondering how asynchronous behavior works. Right now I’m ’bout to slap you like Bruce Lee slapped that boy in Enter the Dragon. (Or was that Return of the Dragon? Maybe it was the game of death? Bonus points to the 1st person that gets the movie correct with a link to the clip on YouTube!) “Don’t focus on the finger or you’ll miss the beauty in the sky above!”, says Bruce. We don’t care about how asynchronous behavior works, as its irrelevant to our design. We only care that our work is done asynchronously! So we’ll code this test in ObjectiveC:

#import
@protocol MyAsynchronousBehavior
-(void) performAsynchronously:(SEL) aSelctor onTarget:(id)aTarget withObject:(id)anObject;
@end

@interface MyWhatzItzTest : SenTestCase <MyAsynchronousBehavior>
{
  MyWhatzItz *myWhatzItz;
  SEL selectorPerformed;
  id targetForSelector;
  id parameterForSelector;
  int performAsynchronouslyInvocationCount;
}
@end

@implementation MyWhatzItzTest

-(void) setUp
{
   myWhatzItz = [[MyWhatzItz alloc] init];
   //The test uses the self-shunt pattern to listen for MyAsynchronousBehavior interaction.
   id theAsynchronousBehavior = self;
   myWhatzItz.asynchronousBehavior = theAsynchronousBehavior;
}

-(void) testMyWhatzItzWillAsynchronouslyDoDisThingWhenAskedToDoDatThing
{
  STAssertEquals(performAsynchronouslyInvocationCount, 0, @"Assuming that we haven't been asked to performAsynchronously");
  [myWhatzItz doDatThing];
  STAssertEquals(performAsynchronouslyInvocationCount, 1, @"We SHOULD HAVE been asked to performAsynchronously");
  STAssertEquals(selectorPerformed, @selector(doDisThing:), @"Should have asked to doDisThing using asynchronous behavior.");
  STAssertEquals(targetForSelector, myWhatzItz, @"Should use myWhatzItz for asynchronous execution.");
}
@end
#pragma mark MyAsynchronousBehavior protocol methods
-(void) performAsynchronously:(SEL) aSelctor onTarget:(id)aTarget withObject:(id)anObject
{
  performAsynchronouslyInvocationCount++; selectorPerformed = aSelctor; targetForSelector = aTarget; parameterForSelector = anObject;
}

Supplying the asynchronous behavior becomes a construction/intialization concern, which could be extracted into a wiring framework like Interface Builder (or if you do Java, Springframework). The nice thing is that we can alternate our asynchronous behavior without touching the rest of the project. We can do something quick/dirty like detachThread… and later get more elegant with RunLoops. Today’s tip comes to you (me) completely by accident. I’ve been trying to test drive things in Java and ObjC for several years now and I’ve never got this part quite right. Feel free to share your opinions/experiences with threads and tests.

**Update**
The above example demonstrates a few important unit testing concepts. first it uses the self-shunt pattern to allow the test to become a mock and listen for interactions between the tested object and its collaborator(s). Second, it demonstrates the importance of using tests to carve out the pieces that should NOT be under test. In this situation it’s multi-tasking, however in other scenarios it could be anything from a DBMS to a network call. I could have illustrated an example where I spin up a Thread pool of some sort from within the test started work, paused the main thread and waited for a response. That’s what I’ve done in the past and it becomes extremely complicated and brittle. In stead, I use the elegance of abstraction to make the test 100% predictable, 200% more simplistic, and 300% more maintainable. Where do I get those statistics? The short answer is they’re sequential. (The long story begins yesterday when my 5yr old spontaneously decided to count from 1 to infinity in the middle of our shopping trip. You see, she only recently learned her numbers up to 100 and after getting to 199 we all realized the child’s computational limits as she continued with one hundred one hundred then followed up with one hundred one hundred one, one hundred one hundred two…)
**Update**

iPhone Boot Camp


Platoon… Attention! Forward… March! About… Face! Platoon… Halt! Parade Rest!… At ease…

Many moons ago I attended boot camp and that’s kinda the jest of it. Sure there were some rifles fired here and some push ups done there. I believe there was even a drill sergeant or two but the above was the general format. Hi, I’m Cliff. You’re probably here because you’re wondering how to fix that EmptyStackException in your XML transform. Or maybe you’re trying to run Blackberry compilers on your MacPro and you keep getting verification errors. Or maybe you just Googled my name and landed here by chance. Whatever the catalyst the net result will be pure edutainment. (Yes edutainment is a “Can’t See Nothing But the Source” exclusive! Remember where you heard it first!) If you are not completely edutained then you’ll probably feel edu-pain.

Back to Boot Camp. That’s where I was privileged to be this past week. Not the original left-right-left boot camp, but a different kind. This boot camp was lead by none other than Aaron Hillegass. He wasn’t as loud as my former Drill sergeant’s Morris, Decker, and Perez (BTW, they would just love to hear me address them without their demanded “Drill Sergeant” prefix), but he did give a lot of quality info on all things Mac and iPhone development related. Tag teaming with Jaun Pablo, Aaron gave a five day hands on shop which involved responding to touch events, in depth networking, iPhone multi-media and more. The second half of the course was all about software development for the Mac desktop. We learned how to build installers, how to auto upgrade via app-casts, how to build quick look and spotlight plugins, and how to overlay Quartz graphics on an Open GL context. Then there was my favorite topic, unit testing. I found out that Apple released support for iPhone unit testing behind my back with their 2.2 SDK release. I’d love to write more about the topic but I have a lot of catching up to do. Shotz out to Aaron and Juan Pablo! Drop a line on whatever and we’ll speak on it.

iPhony Frameworks


So I’m writin’ all kinds of Objective-C code, right? And I’m finally in my element because I got Google Tools For Mac doin’ the SenTest thing, right? I even figured out how to include modules using project relative paths. That’s when my trouble started. Y’see, I thought frameworks were no different than modules. Of course they’re different or else they wouldn’t be called frameworks! Still, I blurred the line between the two. So then I’m writing all these gnarly tests using OCMock. Remember OCMock? I complained on the forums about adding it to an iPhone project. then I finally found a hack to get it to run in my iPhone tests. Then the whole module thing started to make me feel warm and fuzzy inside so I thought I had a better approach. At any rate, I tried the same approach with Hamcrest, a tool advertised on the OCMock home page. I couldn’t get it to work. Finally, it dawned on me! You can’t add frameworks to iPhone projects! [Honestly it didn’t dawn on me, I had to be told then re-told by someone who knows waaay more about iPhone stuff than me.]

The point is that Frameworks in XCode iPhone projects don’t work like modules. With a module, you can just drag/drop the module file into your project, set its dependencies in your target, build and then you’re off and running. Frameworks are different. Frameworks have to exist (to the best of my knowledge and until someone who knows stuff tells me some new stuff) under /Library/Frameworks in order for SenTest test cases to use them. Frameworks can not be used at all during run time in an iPhone project. I don’t even think they’ll run in the Simulator which means no debugging unit test code, which means you better write some very fine grained unit tests which turns out to be necessary anyhow. That’s the point. You can’t run Framework code in an iPhone project but you can run it in a GTMSenTestCase as part of the build (not build/go process). If anybody knows better speak up now or I’ll forever hold out the peace sign.

The Leg Bone’s connected to the…???


No matter how many times I tell my four year old back, up she continues to play kiss the door knob. No matter how many times I warn my 9 year old to thumb-tack her book-bag to her spine in the morning, she continues to show up at school sans knapsack. I somehow believe my kids enjoy hard times, appreciate the torture of incinerating your appendages on the hot oven door, and outright live for the moment somebody will come crashing through the doorway embedding the door handle in a young forehead. Then I realize there are certain things that they won’t include in the text books… certain things they won’t teach in class or during an online tutorial. These are the things you have to find out by smashing your nose, breaking your arm, and making an absolute fool of yourself. It’s the first step in agile development is it not? It’s the red before the green-refactor, isn’t it? It is amazing to watch the test driven antics in somebody less than half your age.

Before I allow George Killian to seep deep enough into my blood stream to rip the original intention out of my cerebrum let me explain what I just learned. Apple’s Interface Builder != Springframework. Sure it tastes like apple pie but there are no apples in it. Here’s the deal. You would think (or you would if you wore an argyle sweater like me) that wiring a UIImageView to your controller would be sufficient enough to make that same UIImageView available when you loaded the controller from a nib file in the main bundle wouldn’t you? [Yes you would because you’re me in this hodge-podge example… just play along! I don’t care if you never heard of a nib file. Nod your head and say uh-huh…] Calling initFromNib on your controller will read in the nib file and eventually perform the internal connections/plumbing but your next statement will be in for a surprise if it attempts to inspect or dig values out of the controller that are connected to other things with Interface Builder’s connect the dots magic. Here’s what I mean. Create an arbitrary UIController named LegBone and give it a HipBone IBOutlet property. (Create a HipBone class in your project.) Create a nib file, open it in Interface Builder and set it’s FilesOwner to LegBone. Drag and drop an object from the library into the nib file’s main window and then connect the legbone to the hip bone. In your app delegate, instantiate the LegBone using the nib file and declare a local variable of type hip-bone while setting it equal to the property from LegBone on the following line. Run all of this in the debugger and watch as XCode reports 0x0 (or null, or is it nil? What’s the doggone difference and can we settle on a universal nomenclature for a value that doesn’t exist across all programming languages???!!!) when you step to and hover over the LegBone.hipbone property assignment. It should look roughly like this (not compiled or cross checked due to laziness):

LegBone.mm

@interface LegBone : UIViewController
   IBOutlet *HipBone hipbone;

@property (nonatomic, retain) IBOutlet *HipBone hipbone;
@end

MyAppDelegate.mm

@implementation MyAppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application {
	LegBone *myLeg  = [[LegBone alloc] 
								 initWithNibName:@"LegBone" bundle:[NSBundle mainBundle]];
        HipBone *hip = [myLeg.hipBone];
        NSLog(@"My hip is %@", hip);
}
@end

Of course after catching the problem the obvious thing to do here is to instantiate the hip in your delegate and set it on the legbone since Cocoa is too lazy/slow/unwilling to do it for you. That brings me to my next surprise. I caught this immediately afterwards but it could have easily been one of those 2 day investigations that check everything but the obvious. Setting the hip bone programmatically without clearing the connect-the-dots magic in InYourFace Buildher will only be undone by the runtime when it finally gets around to connecting your dots during runtime. In other words, say you have this:

@implementation MyAppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application {
	LegBone *myLeg  = [[LegBone alloc] 
								 initWithNibName:@"LegBone" bundle:[NSBundle mainBundle]];
        HipBone *hip = [[HipBone alloc] init];
        myLeg.hipBone = hip;
        NSLog(@"My hip is %@", hip);
}
@end

And pretend you forgot to remove the HipBone object in Innerplace Biller. You’ll fix the nil pointer in the app delegate but then inside LegBone you will be talking to a different hip. For a beginner like myself, trial and error will likely never show the core problem. You have to know what to look for. You have to know that wiring is performed at runtime and possibly at a later stage or in an entirely different method. It’s like Dr. House says, “When something doesn’t make sense, one of your assumptions is wrong.” In this case you would assume that initializing a controller from a pre-wired nib will instantiate all of your nib file’s internal objects and prime all of the setters. You would assume that these things happen before control returns to the next statement as it would if you were loading a Spring beand factory and asking for a bean. That’s all for now. I’m going night-night.