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.

Subversion 1.5 and XCode 3.1.2


Why don’t somebody fix this already? I think I finally got the latest XCode 3.1.2 to work with the latest Subversion 1.5 release. This was after downloading the latest 2.2 iPhone SDK. I scoured the web and found the best tip here. There’s another possible more automated solution here but because I don’t feel comfortable running a bash script I copied off of some web page (try it and you’ll cuss. Then you’ll see what I mean!) I went with the other approach. I’ll shorthand the steps I followed below because following the first link above, I think, misses some important files and doesn’t work correctly. The general idea is to copy your Subversion installed libraries (assuming you used the Collab.net bundle) into the place where XCode binds to.

From your home directory:
mkdir svn-bkup
sudo cp /usr/lib/libsvn_* svn-bkup
sudo cp /usr/lib/libapr-1.dylib svn-bkup
sudo cp /usr/lib/libaprutil-1.dylib svn-bkup

sudo cp /opt/subversion/lib/libapr-1.dylib /usr/lib
sudo cp /opt/subversion/lib/libaprutil-1.dylib /usr/lib
sudo cp /opt/subversion/lib/libsvn_* /usr/lib

[restart xcode]

That’s what I did and now it no longer complains “error 155021 this Subversion client is too old and stoopid to work with your shiny new svn checkout that’s just bananas!” Your error message may vary but the concept is the same.

This message is brought to you, in part, by the proud sponsors listed in the Hall of Aim.

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.

Dynamic Dispatch Discrepancy


*Update*
By the way I unsuccessfully tried overriding the methods() method and almost went as far as overriding send on my mock wrapping ObjCMock class. My experience in MOP tells me that overriding send is likely rooted in trouble so I decided against it.

Yesterday’s Ruby drama ended with my finding a hack around the dropped parameters. If I was more familiar with Ruby, had more time to kill, or if it were Groovy instead then my solution would be much cleaner.

The problem:
Ruby Mocks under RSpec (have no idea if the problem persists in other Ruby scripting environments) do not receive parameters correctly from native Cocoa objects.

The hack:
Use a home-grown mock to intercept the parameter and pass along to the Ruby mock.

The code: (bowling_controller_spec.rb)

require File.dirname(__FILE__) + ‘/test_helper’

require “BowlingController.bundle”
OSX::ns_import :BowlingController
OSX::ns_import :BowlingProtocol
require ‘delegate’

include OSX

class ObjCMock
attr_accessor :delegate
def roll(num)
@delegate.roll(num)
end

# def method_missing(m, *args)
# puts “Forwarding message”
# @delegate.send(m, args)
# end

def initialize(theMock)
@delegate = theMock
end
end

describe BowlingController do
before(:each) do
@controller = BowlingController.new
@bowling = mock(‘BowlingProtocol’)
@text_field = mock(‘Pins’)
@text_field.stub!(:intValue).and_return(10)
@controller.pins = @text_field
end

it “should roll a ball” do
@controller.roll
end

it “should roll a ball and get the value from the pins outlet” do
@text_field.should_receive(:intValue).and_return(0)
@controller.roll
end

it “should be an OSX::NSObject” do
@controller.is_a?(OSX::NSObject).should == true
end

it “should have an outlet to a bowling object” do
@controller.bowling = @bowling
end

it “should send the pin value to the bowling object” do
@controller.bowling = ObjCMock.new(@bowling)
# @controller.bowling = @bowling
@bowling.should_receive(:roll).with(NSNumber.numberWithInt(10))

@controller.roll
end
end

I left in the commented out method_missing magic that doesn’t work the way I’d expect it. Ideally I’d like to tuck this wrapping mock to the side without needing to define the specific signature I’m mocking. Ideally method_missing would give me the ability to answer any message. Alas, I get “does not reckognize selector” errors from NSProxy when I enable it. I have a feeling that NSProxy probably looks through the defined methods on it’s delegate and throws this error without 1st trying to invoke the method… effectively killing any dynamic magic ability from objects passed into Cocoa land. I also have a feeling that there are a few other holes in the proxy approach with Ruby/Cocoa. If anybody happens to know the details feel free to chime in.

RSpec for iPhone development


So last night I did some laundry, taught my oldest daughter how to write code, took both of my girls shoe shopping, washed the little one’s hair, raked the leaves cooked dinner, then finally got a start on trying RSpec against a Cocoa Touch controller class. Yep, I was kinda sorta busy. Had I a little more time I wouldn’t be stumped where I am now but since my schedule is as packed as a VW beetle carrying a family of 6 on a Ski vacation for 2 months there’s little wiggle room for discovery and surprises, so instead I ask you, my humble readers (all three of you) to figure out the hard stuff for me. I will gladly repay you by splattering your hard work across the internets next to a picture of my smiling eyebrows and deep claims referencing my name exclusively.

I’m working through a Bowled over by Ruby/Cocoa example written against Mac OSX Cocoa APIs and trying to adapt it to CocoaTouch. The first challenge comes from trying to use RubyCocoa to access a controller bound to certain CocoaTouch APIs like UIKit. It doesn’t work. So instead I was clever enough to side step the problem and generate my BowlingController as a vanilla NSObject using the “script/generate model” command from Dr. Nic’s RBiPhoneTest. I use rbiPhoneTest to setup the project test structure as well so now I have a rake file in my root that I use to build the necessary BowlingController.bundle for RSpec (or any Ruby code) to access. I will plan a write up on all of this after I get through the entire tutorial. Long story lengthened I have RSpec loading and running my BowlingController, I’ve made several iterations even into creating IBOutlet/IBAction bindings for Interface Builder. (I’m not sure if they work b/c I haven’t gotten that far yet.) I get stuck at the part where my controller is supposed to pass the pins value from the text field into the bowling model object. My Ruby bowling stub reports that roll has been invoked with no arguments even though I am most definitely passing a value into the method. I keep getting, “Spec::Mocks::MockExpectationError in ‘OSX::BowlingController should send the pin value to the bowling object’
Mock ‘Bowling’ expected :roll with (10) but received it with (no args)
./test/bowling_controller_spec.rb:38:”
I’ve even went as far as passing a literal 10 into the call. At this point it looks like some sort of Ruby/Cocoa alignment issue or something.

bowling_controller_spec.rb

require File.dirname(__FILE__) + ‘/test_helper’

require “BowlingController.bundle”
OSX::ns_import :BowlingController

include OSX

describe BowlingController do
before(:each) do
@controller = BowlingController.new
@bowling = mock(‘Bowling’)
@text_field = mock(‘Pins’)
@text_field.stub!(:intValue).and_return(10)
@controller.pins = @text_field
end

it “should roll a ball” do
@controller.roll
end

it “should roll a ball and get the value from the pins outlet” do
@text_field.should_receive(:intValue).and_return(0)
@controller.roll
end

it “should be an OSX::NSObject” do
@controller.is_a?(OSX::NSObject).should == true
end

it “should have an outlet to a bowling object” do
@controller.bowling = @bowling
end

it “should send the pin value to the bowling object” do
@controller.bowling = @bowling
@bowling.should_receive(:roll).with(10)

@controller.roll
end
end

BowlingController.h

#import

@class UITextField;
@class Bowling;

@interface BowlingController : NSObject {
UITextField* pins;
Bowling* bowling;
}
@property (nonatomic, retain) UITextField* pins;
@property (nonatomic, retain) Bowling* bowling;

-(void) roll;
@end

BowlingController.m

#import “BowlingController.h”
#import “Bowling.h”

@implementation BowlingController
@synthesize pins;
@synthesize bowling;

-(void) roll{
[self.bowling roll:[self.pins intValue]];
}

@end

// This initialization function gets called when we import the Ruby module.
// It doesn’t need to do anything because the RubyCocoa bridge will do
// all the initialization work.
// The rbiphonetest test framework automatically generates bundles for
// each objective-c class containing the following line. These
// can be used by your tests.
void Init_BowlingController() { }

Bowling.h

#import

@interface Bowling : NSObject {

}
– (void) roll:(int) pins;
@end

Bowling.m

#import “Bowling.h”

@implementation Bowling
– (void) roll:(int) pins{
}

@end

// This initialization function gets called when we import the Ruby module.
// It doesn’t need to do anything because the RubyCocoa bridge will do
// all the initialization work.
// The rbiphonetest test framework automatically generates bundles for
// each objective-c class containing the following line. These
// can be used by your tests.
void Init_Bowling() { }

Note to self: I gotta find better analogies. These are really starting to suck.

Murder me!


I’m spending too much time trying to figure out how to assert that a string is properly URL encoded! I refuse to take the traditional approach of running code in the application and peeking through debugger goggles or some obscure log output. Unit tests are made for this sorta thing! I’e had some tips that suggest how to perform URL encoding but experience teaches me not to trust any particular tip unless I can confirm it in a learning unit test. That’s how I self-educated myself on Ruby over the weekend. I wrote a bunch of learning tests to confirm every code snippet I read online. So why is it that when I assert @”ab%%c” == @”ab c” the error message echoes back “ab != ab c”??? I’m using Google tools for Mac to run iPhone unit test suites.

One other thing… could somebody please invent/has somebody invented an “automatic add new files to svn” plugin for XCode? If I botch one more commit my team is going to cut off my water supply and replace my contact lens solution with Windsor’s clear hot sauce. I love the clear stuff because I can dump a whole bunch on my meal without my wife nagging me about my heartburn.

Objective C, Almost closures?


I’m about toe deep in ObjC and Cocoa and I’m starting to get that warm fuzzy feeling everytime I message and object without needing a type cast. I get really warm/fuzzy when I use @selector() to throw extra executable logic from a long running process back onto the main thread. Now I’m thinking about the @selector idea and wondering how close it is to closures. I’d like to be able to define a method on an interface… *ahem* …protocol that takes a selector as a form of callback. Though Cocoa makes extensive use of delegates I don’t want to haff to set a delegate instance variable and define another protocol for something as simple as an inlined callback operation. In other words I wanna say: “Mr. Object, do dis stuff when your data becomes available.” Back into the manuals to learn about @selectors.

XCode refactoring sux!


The title may be slightly exaggerated but when you grow used to a tool like IntelliJ Idea you start to become spoiled by everything it gives you. First off refactoring support in Idea is second to NONE! Honestly, there are no front runners. When you code in Idea you can literally feel the text of the source code under your finger tips. Now going from Idea to, say Eclipse isn’t too bad because Eclipse supports 98% of the refactorings that Idea has out of the box but it likes to torture you with dialog boxes. (I don’t like to be prompted or questioned when I know what I’m doing. If I ask to extract a method, or variable or rename something don’t give me some damned options just do what I ask!!!) Now going from Idea to something like visual C++.. phew!!! Talk about shell shock! Let’s just say it’s nice and toasty in the Idea house while somebody in the MSDN camp forgot to pay PPL. Ok now let’s move from Idea to XCode. Not as frigid as it was when we bolted butt-naked into Redmond with VS but still pretty darned cold. Why am I complaining?

Typical use case:
Dev guy writes a method. Dev guy later sees that he picked a dumb name for said method. (The method name should be a generic toggleView not a specific gotoTheVerySpecificUseCaseViewThatIThoughtOfAt10pmWhileIWasDrinkingPabstBeer) Now in Idea I use a hot-key on the method name type the new name and click run. (Nobody taps me on the shoulder to ask me if I’d like fries with that refactoring as they do in Eclipse land.) I just tried that fancy recipe in XCode and when I run I get an error. I didn’t even look at the details when GDB started to grind and slow the vent handling. I already knew from the last time I tried right-click and refactor a method name from the implementation. The refactorer doesn’t get those tough to reach spots. You know how when you ask you daughter to clean her room and she only gets the visible areas but you really wanted her to clean the back of that nasty closet? Or like when you buy one of those store brand toothbrushes with the labeling “Each! Compare to Reach toothbrush…” In other words, there were remnants left behind from the refactoring. This is completely unacceptable! As much as Apple pays attention to detail in their products I’d expect nothing less than perfection in their IDE! I don’t think this is an area where I’m misusing the tool either. refactor/rename should understand the Cocoa environment well enough to understand that I need IBOutlets referenced in nib files updated as well. I guarantee you that the folks at JetBrains would not have left this stone unturned.

What’s the difference?


It”s late and I’m stumped. Trying to figure out what’s the difference between

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"Cell";
	UITableViewCell *cell = [tableView
							 dequeueReusableCellWithIdentifier:CellIdentifier];
	if (cell == nil) {
		cell = [[[UITableViewCell alloc]
				 initWithFrame:CGRectZero
				 reuseIdentifier:CellIdentifier] autorelease];
	}
	cell.text = [teams objectAtIndex:indexPath.row];
	return cell;
}

and:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
	UITableViewCell *cell = [tableView
							 dequeueReusableCellWithIdentifier:@"Cell"];
	if (cell == nil) {
		cell = [[[UITableViewCell alloc]
				 initWithFrame:CGRectZero
				 reuseIdentifier:@"Cell"] autorelease];
	}
	cell.text = [teams objectAtIndex:indexPath.row];
	return cell;
}

I’ve seen this pattern twice, once in an iPhone SDK book and once in code generated by XCode. That’s enough to make me feel like there’s a reason we use a temp variable here. (Incidentally I didn’t notice the redundancy in my refactoring until I pasted/posted the code snippet. If the motivation is merely to cut down redundancy then I’m fine with that, I just wanna make sure I’m not missing something important.)