Update (July 30, 2012):

If you've upgraded to Mountain Lion the below instructions still work. Once complete you should check out this guide. It contains a tip on installing gcc via brew in order to avoid using CLANG which can result in occasional errors when installing/updating gems.

--- End of update ---

A few weeks back I decided to take the plunge and wipe my machine and set it up from scratch. The main reason being I was running out of space on my SSD and I just wanted to see what a fresh Lion install would be like.

Let me tell you, its FAST! Totally worth it. It did take me some time to find the right resources and shave some yaks so this is more of a guide for future-me to save some time. If you do carry on reading from this point I assume you know what you're doing :)

So now that everything is wiped and fresh and new (backed up of course) the main task is setting up ye old dev environment. Lets start at the beginning.

Xcode

Head over to the Mac App Store and download Xcode. Once you install it you'll find that it no longer lives in /Developer. Its been moved to /Applications and its command line tools are no longer in the $PATH on the command line.

We don't have to add them ourselves, simply start up Xcode, go to Preferences and then Downloads > Components. Click on the "Install" button next to "Command Line Tools".

Heroku

If you're deploying stuff on Heroku, grab the toolbelt here.

Homebrew

Previously I was using MacPorts, but after hearing so many great things about Homebrew I took the plunge. Its simply a great package manager and you can download it here. For example, OS X doesn't ship with wget, so to install it you can simply run the following on the command line:

brew install wget

Done. Moving on.

RVM

RVM is a command-line tool which allows you to easily install, manage, and work with multiple ruby environments from interpreters to sets of gems.

What it says on the tin. It allows you to easily install multiple versions of Ruby on your system. It also allows you create gem sets and swap between them. To install:

bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)

Then:

source ~/.rvm/scripts/rvm

Now we're ready to install Ruby! The only problem is that with Xcode 4 the provided compiler (gcc) is LLVM based and not yet fully supported by Ruby and gems. Now before you go hunting for an older gcc (which I did) its not necessary.

To install Ruby 1.9.2 (which is required for Heroku) enter:

rvm install 1.9.2 --with-gcc=clang

When that is done, lets check what version of Ruby we have set as the system default:

ruby --version

Mine said Ruby 1.8.7. Lets set 1.9.2 to be default:

rvm use 1.9.2 --default

If you run ruby --version it should now say 1.9.2. If you ever want to go back to the system default simply enter rvm system. So now we have an easy way of swapping Ruby versions and you can read more about it here.

Sublime Text

Sublime Text is my favourite editor of all time. Get it here. Read some great tips and tricks here.

MySQL

Previously I was using MAMP. However I had an issue installing the do_mysql gem which is required for dm-mysql-adapter I was using with Datamapper.

Long story short I found the easiest thing to do was install mysql via brew instead of using MAMP. So to start off:

brew install mysql

Next to configure the installation (all one line):

mysql_install_db --verbose --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp

To get it to run on startup, first we have to create the directory if it doesn't exist:

mkdir -p ~/Library/LaunchAgents

Then we copy the mysql.plist over (the version number may have changed when you're reading this):

cp /usr/local/Cellar/mysql/5.5.20/homebrew.mxcl.mysql.plist ~/Library/LaunchAgents/

Then we tell launchctl to load it on startup:

launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist

Now to set the password:

mysqladmin -u root password {new-password}

Phew! Ok, now mysql is installed and running on port 3306. To create your first database simply enter:

mysqladmin -u root -p create {your-database-name}

And some gem love...

Finally I recommend using bundler for gem management, foreman to run your app (especially if you're on Heroku), rerun to rerun your app when something changes, datamapper for ORM and sinatra for happiness.

Good luck!

Posted
AuthorPaulo Fierro

I just bought Reflection about 20 minutes ago and its awesome. It allows you to AirPlay mirror your iPhone 4S or iPad 2 to any Mac running Snow Leopard or later over WiFi. This is fantastic because in the past we had three options:

  1. Use the Simulator, but there are certain features (gestures, accelerometer, etc) that are hard or impossible to demo. Yes there may be tools to help us with some of them, but its a pain
  2. Set up some sort of camera rig to film what it is we're demoing. The nicest one I've seen is Heiko Behrens' CamHolder. I saw one of his earlier prototypes at Beyond Tellerand last year and its a great idea, but it means extra stuff to carry.
  3. Bring an Apple TV with you, hope the projector supports HDMI or buy an HDMI to DVI/VGA converter and AirPlay mirror to that. But then there's the issue of swapping displays, the time lag while swapping and hoping the projector is up to task. And you have to bring it with you.

Those days are long gone! This is what I will be doing in the future:

Step 1: Set up Reflection

Download the app, install and run it. Now ensure your Mac and iOS device are on the same WiFi network. If there is no WiFi available, create a wireless network on your Mac or share the wired connection. Now connect your device to this newly created network.

On your iOS device, double tap the home button, scroll all the way to the left and tap the AirPlay button. Select your Mac from the list of available options and select the Mirroring option.

You should now see a mirror image of the iOS device on your Mac. Finally enter full screen mode (Device > Enter Full Screen) or press CMD+F. Reflection will go into its own full screen space thing.

Step 2: Set up Keynote

Open up Keynote and any presentation. Go to Preferences > Slideshow and enable "Allow Expose, Dashboard and others to use screen".

Step 3: Awesome

Now for the fun part. Enter full screen mode in Keynote and then hit Play to start the presentation. Three finger horizontal swipe on your trackpad to swap to the Reflection app, showing your iOS device in full screen. Three finger swipe back to go back to your presentation.

How freaking cool is that? No swapping displays, no lag, no lugging extra kit with you, just ultra-smooth swipy goodness.

Yeah, I like this a lot.

PS: I have only tested this on Mountain Lion. I assume it works on Lion, no idea about Snow Leopard.

Update: Mike confirms it works on Snow Leopard in the comments. Wicked!

Posted
AuthorPaulo Fierro

This time last week marked the end of Flash on the Beach as we know it. The end of what I have always considered the best fucking conference I've ever attended. John Davey who organises it, always pours his heart and soul into it along with his wife and team of volunteers and it shows. FOTB has a special place in my heart for various reasons.

I remember sitting at my desk, working at a startup in Norway talking to some friends over IM who had just come back from the first one in 2006 ranting and raving about how amazing it had been. I decided then and there that I was going to the one next year even if it meant taking some vacation time because this was obviously something I had to experience for myself.

So in 2007 I flew over in November and stayed at a very simple bed and breakfast in Kemptown where I could marvel at the rainbow flags. Thanks to my good friend Chris Pelsor I managed to meet pretty much everybody who I had followed through the years, via their blogs and work. These were "rockstars", people who's work amazed me and yet, at the end of the day were just people. People like you and I, most of them awesome, some of them extremely shy. I think that was my biggest take away from the conference and something FOTB gets right every time. There is so much mingling between attendees and speakers that it sort of becomes this one collective mass of people who enjoy making cool shit. How can that not be fun.

Most importantly though had it not been for FOTB I would've probably never have come over to Brighton and fallen in love with the city. I would have not come over the following years, gotten to know a certain someone better only to eventually fall head over heels in love and leave everything behind to move to this very city and set up shop here.

So for that reason alone I owe John and FOTB a huge amount of thanks. It may not have been the main reason but it certainly was a catalyst to changing my life. Damn.

But this year was different in one way. I was speaking.

When I was asked at the end of last year I said fuck yes, and then had several months of getting to grips with that idea. I haven't done an enormous amount of speaking - mostly user group sessions, a Flash Camp in Lisbon (which was ridiculous amounts of fun) and a remote session for a one-day conference in Ottawa. But FOTB was special and therefore the goal was simple - don't fuck it up.

The week before I would have been nervous but Niqui, Matt and I were still working on finishing this year's conference guide, a web app you can play with at fotb.me. How we built that is another blog post.

The only problem was my slot. I was speaking on Wednesday, right before lunch. This meant I couldn't really enjoy myself fully on Monday and Tuesday as I couldn't properly relax. No biggy, but hey. I was probably the only person who woke up Wednesday morning without a massive hangover so I guess I win :)

I feel that the session itself went well. I got some great feedback and was actually amazed at all the people that showed up. Being up against the JAM session, and Lee Brimelow from Adobe who stole the show at the Keynote I was expecting the room to be empty. Especially with the JAM session being described as:

"Rest assured, whatever we ask them, it will be hot! This is a session you need to put on your personal scheduler so that you don't miss it!"

Thanks John.

I did consider changing this and Lee's description to "Probably shit. Don't bother going."

Alas, the Pavilion Theatre (the little of the three venues) was actually half full. I was super impressed and if you were there, thank you :) There were several friends in the audience which only made it easier. The lighting guy made them all disappear too - in retrospect I think seeing people's faces might have been better. This was a smaller crowd than Lisbon for sure, but it was still FOTB. Don't fuck it up.

My favourite piece of feedback was from Neil Keith Young:

I then went into the Pavillion Theatre to see Paulo Fierro talk about his development of iPhone applications. His talk about developing and releasing an application through the app store was fantastic. He talked through his development of a Boris Bikes iPhone application for the Norwegian market and discussed the pit falls and also the excitement generated from building the application. Truly inspirational stuff and something that I would really love to look at, even if not from an Objective C application then from a html 5 website standpoint.

I owe this man a beer.

The guys at Ubelly also took some notes as well as Jens Brynildsen on Flash Magazine. He also took this pic where I have a pointier chin than Leno!

Anyways, enough about me. I wish I had gotten to see more sessions but I missed everything on Monday except the last two because I was in a state of panic going over my slides. I say going over, I mean recreating them because they original ones weren't good enough. Takes alot longer than you think.

My favourite sessions were Lee's bit of the keynote (hilarious), Jon Burgerman (who could happily leave painting for standup), Joel Gethin Lewis (who is actually helping people through technology. amazing), Remy Sharp (who got sung happy birthday twice! bet the W3C don't do that shit), Cyriak Harris (madman doing live AfterEffects'ing), Jared Ficklin (smoke machines mean instant win) and Josh Davis (who scares the shit out of me).

There are so many I would have loved to have seen but hopefully the videos will make it online sometime soon. Another highlight was the debauchery that happened at MyHotel. Less so than previous years, but still tons of fun. The Zacapa... mmm. The speaker discount didn't hurt either :)

Anyways, another year, another awesome FOTB. I'm really looking forward to what next year brings and hopefully once again see all of these wonderful friends who live in interesting places all over the world descend upon our little village once more, for whatever the new FOTB becomes.

Posted
AuthorPaulo Fierro

In a forthcoming blogpost I'll talk about not only the awesome Flash on the Beach conference that just flew by but also the web-app we built for it at fotb.me.

In one of the many bar chats, I was talking to Paul King about our experience building it and he asked if we'd played around with the accelerometer data. I said we had, albeit briefly and I incorrectly stated that we had gotten it working on iOS, Android and PlayBook.

iOS 4.2+ devices support the DeviceMotion API and so does the PlayBook. The only gotchas is that instead of listening for the devicemotion event you have to hook into the window.ondevicemotion function itself for this to work on the PlayBook.

For Android phones I quickly threw together a SWF that would simply listen to a flash.sensors.Accelerometer instance and then send those over ExternalInterface to a JavaScript handler which then takes it from there.

This is an extremely basic example, but all the code is on GitHub so get it there or check the demo. Since the PlayBook supports both Flash and devicemotion a simple check is done so we don't get the data twice.

It should go without saying that if your Android phone doesn't have Flash installed then you get nothing.

Posted
AuthorPaulo Fierro

When we were developing fotb.me we ensured the app would run offline using the fancy, new HTML5 app cache API. It can be a pain to create the cache manifest file by hand, this is obviously something that should be automated.

I looked around and found a plugin for Coda and a bundle for TextMate and TextWrangler which are good, but they don't allow me to ignore certain files and only add certain filetypes which were two things I needed. Not wanting to have to remember to edit the generated files manually I rolled our own.

CacheManifestGenerator is a simple Ruby script that traverses any folder recursively and makes a note of each file. You can add specific files to be ignored and the specific file extensions to look for. Very, very simple yet effective.

It also adds a comment with the time of creation. This is enough to trigger browsers to check the manifest contents as the file itself is different.

Oh and btw, Ruby is fun!

Update:

John Allsopp reminded me of manifestR, an online tool that creates a manifest for any page you are visiting via a bookmarklet. Very cool stuff, but it didn't work for us as the site has to be online, not be password protected (something we were avoiding pre-launch) and also the ignore files bit I mentioned above. However if you don't need those things then its definitely the easiest way of generating a manifest automatically.

Posted
AuthorPaulo Fierro

When creating web apps that are targeting iOS devices Apple provides a few hooks to allow things such as custom home-screen icons and splash screens for when people add them to their home screen. For icons you simply add the following to the <head> tag:

<link rel="apple-touch-icon" href="icon.png" />

If you want an icon without the default gloss you add -precomposed:

<link rel="apple-touch-icon-precomposed" href="icon.png" />

Different devices will need different sized images. The default of 57x57 is for older iOS devices, if you're targeting iPad you want 72x72 and if you're going to look good on the retina display on iPhone 4 you want 114x114. To tell the device which ones are present there is a sizes attribute where you can supply the size. So it looks like:

<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/images/icon-ipad.png" />
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/images/icon-iphone4.png" />
<link rel="apple-touch-icon-precomposed" href="/images/icon-iphone.png" />

Notice how the last, default one does not have a sizes attribute - it doesn't need it. However, we found that it has to go last otherwise it may get overlooked on iOS3 devices.

Retina display splash screens

So far so good right? Well not so fast. Sadly Apple has not provided the same level of flexibility for splash screens. The sizes property does not work and there is no official documentation on how to provide a high-quality image for retina displays.

Disappointing but I suppose its currently an unsupported feature. Bleeding edge, cuts, etc.

Using media queries

Googling around you'll find lots of people asking this question but none of the solutions I tried worked. Some suggested using the aforementioned sizes property. Others suggest using media queries to target the right device. This does work for iPad and you can target a splash screen for landscape or portrait as follows:

<link rel="apple-touch-startup-image" href="/images/splash-ipad-landscape.png"  
media="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape)" />
<link rel="apple-touch-startup-image" href="/images/splash-ipad-portrait.png" media="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait)" />

The only strange thing is that the landscape splash image must be 748x1024 and you have to rotate the contents 90 degrees counter-clockwise. For portrait the dimensions are 768x1004.

So the logical thing would be to use the same sort of thing for targeting retina display. The regular splash image is 320x460 and the high-quality one is 640x920, so we were thinking we could target the right device using something like:

<link rel="apple-touch-startup-image" href="/images/splash-iphone.png" 
media="(max-device-width: 480px) and not (min-device-pixel-ratio: 2)" />
<link rel="apple-touch-startup-image" href="/images/splash-iphone4.png" media="(max-device-width: 480px) and (min-device-pixel-ratio: 2)" />

The first image is for devices that do not have a minimum device pixel ratio of 2. Sadly this does not work at all. So media queries do work for iPad detection and even iPad start orientation but not for iPhone 4. Frustrating.

PS: adding the -webkit prefix to min-device-pixel-ratio has no effect, I saw this a few places too.

So in an act of desperation we turned to JavaScript. We can check what type of device you are and if you have a retina display so we can try to inject an image for these devices. Select for spoiler alert -> this works.

JavaScript to the rescue

The logic is as follows:

  1. wait for when the document is ready
  2. check that the device is running iOS
  3. check that the device has a retina display
  4. check that the device is running iOS5 or above

The last point is important because an iPhone 4 running iOS4 does not support high-quality splash images (640x920) and will simply ignore any you provide. They don't display the low quality (320x460) one either, they just flat out refuse to display a splash image because you told it to do something it couldn't do. Its a bit touchy.

In any case we use jQuery to figure out when we have loaded, and general DOM magic allowing us to insert the high-resolution splash screen into the <head>, but only for iOS devices with a retina display running iOS5 or later.

function hasRetinaDisplay() {
	return (window.devicePixelRatio >= 2);
}
function isAppleDevice() {
	return (/iphone|ipod|ipad/gi).test(navigator.platform);
}
function iOSNewerThan(majorVersion) {
	if(isAppleDevice()) {
		// Check the version
		var pattern = /iPhone OS (.*) like Mac/;
		var result  = navigator.userAgent.match(pattern); // Returns "iPhone OS X_Y like Mac, X_Y"
		var version = result[1].split(''); // Returns X, Y
		var release = version[0];
		return (release >= majorVersion);
	}
	return false;
}

// When we're ready to go...
$(document).ready(function() { 
	if(hasRetinaDisplay() && iOSNewerThan(5)) { 
		var highResSplash = '<link rel="apple-touch-startup-image" href="/images/splash-iphone4.png" />'; 
		$('head').append(highResSplash); 
	}
});

So this is our CSS:

<link rel="apple-touch-startup-image" href="/images/splash-ipad-landscape.png"  
media="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape)" />

<link rel="apple-touch-startup-image" href="/images/splash-ipad-portrait.png" 
media="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait)" />

<!-- iPhone 4 devices running iOS5+ will get a high-res one via magic JS -->
<link rel="apple-touch-startup-image" href="/images/ios/splash-iphone.png" media="screen and (max-device-width: 320)" />

To sum up:

  • iPads will get the a splash screen for each orientation,
  • non-retina display iOS devices will get the lower quality image,
  • iPhone 4's running iOS4 will get the lower quality image (sadly), but
  • iPhone 4's running iOS5 or above will get a glorious, high-quality image (depending on your design skillz of course).

Hopefully Apple will sort this out in iOS5 and add support for the sizes attribute to the splash screen (or something cleverer). As it stands it appears to be very much an unsupported feature but, getting a high-res splash image on my phone? Totally worth it.

Posted
AuthorPaulo Fierro

Sometimes you see something so obvious, yet totally original that just seems like the "proper" way of doing it. The latest case for me was in atebits' Tweetie 2 for iPhone. The tab bar has a tiny arrow that animates to indicate the currently selected tab item. In addition to a custom, yet standard indication by turning the icon blue-ish this small animation just makes it even more clear to the user where they are.

So in the tradition of stealing great ideas I tried to find out how to do this. Queue Picasso quote here. Anyways, turns out it was fairly simple - it came down to:

  1. creating a view to contain a TabBarController and be its delegate
  2. adding an indicator image to the TabBarController's tab bar
  3. animating the image to the selected tab bar index when the TabBarController's didSelectViewController method is fired

I created a small Xcode project (following the NIB-less way) that shows how I cloned it. You can see it in action below:

You can download the Xcode project here. Next up is the pull-down to reload mechanism :)

Posted
AuthorPaulo Fierro

After doing this whole iPhone development thing for a little over a year now I've realized that I hardly ever use Interface Builder. Sometimes I'll create a dummy NIB, drag in some control and use the panels to find what certain things are called which makes it easier to search through help. But otherwise I simply don't use it, kind of like in Dreamweaver or FlexBuilder where I never use the Design view - eventually you start to render this stuff in your head.

Which I suppose is a little scary.

Anyways, another thing I found was that I never really grokked the whole Interface Builder way of dragging outlets back and forth - I'd often drag something wrong and the whole project would just stop working. Finding out what had gone wrong wasn't always the easiest thing in the world.

So I decided to figure out exactly how I could go about avoiding using Interface Builder at all. You can create your own custom UIViewControllers etc, using nothing but code which is a nice start - and, maybe its subjective, but I do feel like they run faster. Maybe its just me.

But the problem was MainWindow.xib. The default NIB, how do I get rid of it? I wanted pure non-NIB based project which may sound silly but hey.

Eventually I found out there are three things you need to do:

  1. Delete MainWindow.xib from the project and send it to Trash. Easy enough
  2. In your project's Resources group, find the Info.plist file remove the entry for "Main nib file base name". Delete the line and save the file
  3. In the Other Sources group, find main.m and modify the following line:
int retVal = UIApplicationMain(argc, argv, nil, nil);

Change this to

int retVal = UIApplicationMain(argc, argv, nil, @"PROJECTAppDelegate");

So if your project is called Cheese, it would be @"CheeseAppDelegate".

Now the project is NIB-less, but because the window is no longer being created in MainWindow.xib we have to do this in code, but its simple enough. In the AppDelegate.m file applicationDidFinishLaunching might look like this:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}

Just add the following line before hand to create it:

window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

For me at least I now feel like I have full-control over what's going on in the project and I sleep better at night. It kinda feels like during a pure AS3 project.

Maybe its completely silly but I'll find out in time :)

Posted
AuthorPaulo Fierro

Great quote from an Art of the Title Sequence interview with Jim Capobianco on the end credits of Wall-E:

Always move.

Don't sit around waiting for approval or something to happen. I have found there is always something to do on your project. Even if it is the smallest thing it keeps the momentum going and momentum is everything. By always moving it gets you that much closer to getting the project done and you stay ahead of the people who feel it is there job to judge and can put a stop to what you are trying to say before you've had a chance to say it.

Like a shark keep moving or die.

How very true.

Posted
AuthorPaulo Fierro