Hipmunk on Daring Fireball
It’s no exaggeration to say I’ve been trying to get my work on Daring Fireball since I started my iPhone development and user experience adventures three years ago. Thrilled to see it finally go down:
…[T]heir custom date picker is simply brilliant. Hipmunk has a good web interface too, but it has nothing on the iPhone interface. This is why native apps matter.
Thanks for the love, John!
I’m especially pleased he calls out the date picker. That was a lot of work to get right and it’s not the sort of thing you can get away with being wrong in something like flight search and still have happy users.
Hipmunk for iPhone
My awesome new job and how I built our awesome new app. Check it out!
The app even won Best Design at LAUNCH 2011.
iPhone Development for Beginners – 2010 Edition
So you want to learn iPhone development. Good for you! It’s an exciting platform with great developer tools and an outstanding community. Let me tell you a bit about the benefits of building an app the right way and show you some great resources to get started.
The most important point: If you want a great application with a user experience you’ll be proud of, build a native application using Apple-blessed developer tools and resources. Apple’s developer tools are outstanding applications and the iPhone frameworks provide useful, battle-tested, mature code that lets you do a lot without reinventing the wheel every time you need to build even basic functionality. Best of all, Apple gives their tools away for free.
An Objective-C wrapper for AudioServicesPlaySystemSound
In Tallymander 2.0 I use a handful of sound effects to provide user feedback. I thought that the amount of code I had to write every time I wanted to play back a sound was a bit cumbersome so I wrote this wrapper around the AudioToolbox C functions I was using.
DCSoundServices.h:
#import <Foundation/Foundation.h> #import <AudioToolbox/AudioToolbox.h> @interface DCSoundServices : NSObject { } + (void)playSoundWithName:(NSString *)fileName type:(NSString *)fileExtension; + (void)vibrateDevice; @end
DCSoundServices.m:
#import "DCSoundServices.h" @implementation DCSoundServices + (void)playSoundWithName:(NSString *)fileName type:(NSString *)fileExtension { CFStringRef cfFileName = (CFStringRef) fileName; CFStringRef cfFileExtension = (CFStringRef) fileExtension; CFBundleRef mainBundle; mainBundle = CFBundleGetMainBundle (); CFURLRef soundURLRef = CFBundleCopyResourceURL (mainBundle, cfFileName, cfFileExtension, NULL); SystemSoundID soundID; AudioServicesCreateSystemSoundID (soundURLRef, &soundID); AudioServicesPlaySystemSound (soundID); CFRelease(soundURLRef); } + (void)vibrateDevice { AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); } @end
Assuming you’ve got a sound file named click.aif in your application bundle, you can play a sound in just one line of code:
[DCSoundServices playSoundWithName:@"click" type:@"aif"]
Or, vibrate the device:
[DCSoundServices vibrateDevice]
Much tidier than having to import AudioToolbox into every UI that ever plays back a sound.
Convert a CSV into a Plist file
Here’s some code from awhile back. It’ll take a CSV and turn it into a Plist file.
The structure works like this:
The first row of your CSV is considered to be the header. The code will use content from the header row to create key names. For every subsequent row, the code will create a dictionary, associating the content of each column with the key names from the header. The dictionaries live in an array which is written out to a Plist file.
This is handy if you’ve got a bunch of spreadsheet-type data you’d like to use as the basis for a static reference in your app. Say, data about the periodic table, airport listings, trivia questions, whatever. You can sift and sort your data in a user-friendly environment like Numbers or Excel, then dump it out to CSV and put this code to work.
It uses cCSVParse to read the CSV file.
// NSLog(@"Converting %@",pathAsString); CSVParser *parser = [CSVParser new]; [parser openFileWithPath:pathAsString]; NSMutableArray *csvContent = [parser parseFile]; [parser closeFile]; if (pathAsString != nil) { NSArray *keyArray = [csvContent objectAtIndex:0]; NSMutableArray *plistOutputArray = [NSMutableArray array]; NSInteger i = 0; for (NSArray *array in csvContent) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; NSInteger keyNumber = 0; for (NSString *string in array) { [dictionary setObject:string forKey:[keyArray objectAtIndex:keyNumber]]; keyNumber++; } if (i > 0) { [plistOutputArray addObject:dictionary]; } i++; } // NSLog(@"Plist output array %@", plistOutputArray); NSMutableString *mutableString = [NSMutableString stringWithString:pathAsString]; [mutableString replaceOccurrencesOfString:@".csv" withString:@".plist" options:nil range:NSMakeRange([mutableString length]-4, 4)]; NSURL *url = [NSURL fileURLWithPath:mutableString]; // NSLog(@"Write to URL %@",url); [plistOutputArray writeToURL:url atomically:YES]; }
That’s from a simple desktop app I built for the purpose. It takes the path of your CSV, via drag-and-drop, then spits out the Plist beside it. You can grab the source at Google Code. You can also download this compiled binary if you want to get crackin’ right away.