WWDC 2010 Review

Still one session to attend about closures in Objective-C, and I’ll call it a week. A little bit of shopping this afternoon in order to spend my last dollars and I’ll be ready for take-off tomorrow afternoon. So it’s time for a little summary of this week.

Overall, it was my first WWDC and I’m very glad I did it, but I probably won’t do it again. San Francisco is definitely a very nice city, and seeing Steve in live, even from very far away in the audience was an interesting experience. I also learnt a few very interesting things and psychologically a conference like this always has the same side-effect on me: first I’m depressed and humbled by all the ambient intelligence, but then it motivates me a lot to move forward, learn and do something about it. So it has definitely been a very positive experience.

Now was it worth the budget I put in it?

MooPlan 1.0 is out!

Yesterday evening has been  quite a night. I was watching a movie with a friend of mine when my cell phone rang, with a US number on screen.

Hi, I’m calling from Apple. I’m finishing the review of your MooPlan app. But I just miss a few things before it can go on sale.

I sent the application for review about a week ago, and 24 hours after that, I received feedback from Apple requesting me to modify 2 icons that infringed Apple’s trademark. No big deal, the app was resubmitted with the hour. And then I didn’t have any news for a whole week, and I was not worried because I had read so many people complain about the slow review process and the impossibility to get in touch with anyone inside Apple.

And then BOOM! A guy from Apple calls me twice the same evening, just to get my application in store as fast as possible. And a few minutes after the second call, TADAAAA! MooPlan 1.0 is ready for sale. Isn’t it great?

So ladies and gentlemen, it’s my pleasure to announce that my first iPhone application is on sale, and you can get it here for $0.99 or €0.79. If you want to know more about what it does, head to the official website.

Just a few thanks:

  • Special thanks to Groovy and Grails communities for producing such a great productive Java platform that allowed me to focus on the iPhone side of things. Grails was really ideal for me: RESTful services are so easy to build, and scaffolding is just great to quickly produce an administration interface. And it was so fast to learn! I didn’t know anything about Groovy and Grails 6 months ago. And thanks also to Guillaume Laforge and his buddies for the tweets.
  • Thanks to all my friends and colleagues who tested the app: Frédéric Navarro, Mounira Hamzaoui, Clément Mary, Geoffrey Bogaert, Thomas Le Goff, Quentin De Mot, Louis Jacomet, Jérôme Vanden Eynde.
  • Thanks to my employer, Axen, for supporting me in this self-training effort.
  • Special thanks to my Geekette friend, who beared with the movie interruption and supported me for the final steps. Hopefully in a few years, we’ll laugh about this screenshot.

So that’s it. I have the feeling that this release could be the beginning of something big. I feel it in my guts. Now it’s up to you guys. And as I read it in a German restaurant last week-end.

If you like it, tell others. If you don’t like it, please tell me.

iPhone ORM Just Rocks

I have been pretty quiet lately, mostly for 2 reasons:

  1. I’ve been busy with betRway.com
  2. I’ve been playing a lot with the iPhone SDK.

I didn’t know anything about Objective-C so it is a challenging experience to go back to the C world, but I’m starting to find it very exciting. After I had read Cocoa Fundamentals and the iPhone Application Programming Guide (very boring stuff, but hardly avoidable), after having gone through “Your First iPhone Application“, I found myself pretty frustrated because I missed a lot of knowledge to jump into sample projects.

Fortunately, I stumbled upon this great blog with plenty of very complete and up-to-date tutorials. There is this especially this TodoList example that taught me how to do most of the things I couldn’t figure out by myself just by reading the code of the Books sample.

But at the end of that tutorial, I realized that a very important part of my code was made of boilerplate and ugly ANSI-C code to setup database stuff, like in the old days of JDBC. Google was my best friend and allowed me to find SQLitePersistentObjects.  And boy it works great! And it makes the code so simpler. Make your own mind:

This used to be the application launching code:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    [self createEditableCopyOfDatabaseIfNeeded];
    [self initializeDatabase];
    // Configure and show the window
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];

// Creates a writable copy of the bundled default database in the application Documents directory.
- (void)createEditableCopyOfDatabaseIfNeeded {
    // First, test for existence.
    BOOL success;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"todo.sqlite"];
    success = [fileManager fileExistsAtPath:writableDBPath];
    if (success) return;
    // The writable database does not exist, so copy the default to the appropriate location.
    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"todo.sqlite"];
    success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
    if (!success) {
        NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);

// Open the database connection and retrieve minimal information for all objects.
- (void)initializeDatabase {
    NSMutableArray *todoArray = [[NSMutableArray alloc] init];
    self.todos = todoArray;
    [todoArray release];
    // The database is stored in the application bundle.
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"todo.sqlite"];
    // Open the database. The database was prepared outside the application.
    if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
        // Get the primary key for all books.
        const char *sql = "SELECT pk FROM todo";
        sqlite3_stmt *statement;
        // Preparing a statement compiles the SQL query into a byte-code program in the SQLite library.
        // The third parameter is either the length of the SQL string or -1 to read up to the first null terminator.       
        if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
            // We "step" through the results - once for each row.
            while (sqlite3_step(statement) == SQLITE_ROW) {
                // The second parameter indicates the column index into the result set.
                int primaryKey = sqlite3_column_int(statement, 0);
                // We avoid the alloc-init-autorelease pattern here because we are in a tight loop and
                // autorelease is slightly more expensive than release. This design choice has nothing to do with
                // actual memory management - at the end of this block of code, all the book objects allocated
                // here will be in memory regardless of whether we use autorelease or release, because they are
                // retained by the books array.
                Todo *td = [[Todo alloc] initWithPrimaryKey:primaryKey database:database];
                [todos addObject:td];
                [td release];
        // "Finalize" the statement - releases the resources associated with the statement.
    } else {
        // Even though the open failed, call close to properly clean up resources.
        NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
        // Additional error handling, as appropriate...

Now it’s just that:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
	NSMutableArray *todoArray = [[NSMutableArray alloc] init];
	self.todos = todoArray;
	[todoArray release];
	[self.todos addObjectsFromArray:[Todo allObjects]];
	// Configure and show the window
	[window addSubview:[navigationController view]];
	[window makeKeyAndVisible];

And this is just one example. All the CRUD operations are so much simpler. And I didn’t even need to create the SQLite database. It’s almost a shame Apple didn’t include such a framework in the SDK. For your curiosity, you can download the project here.

I love it! Now I should be able to get my hands dirty with my real project. More on that later ;o)