Tuesday, December 23, 2008

Apple rejects iBoobs application

The Register has their typically humorous take on the iBoobs application by Mystic Game Development that was recently rejected by Apple (complete with a YouTube video of the game in action :-).

Monday, December 22, 2008

ABPerson flags followup

In my entry about ABPerson flags, I said that the kABPersonFlags property returns an NSString* that contains an integer. Actually, after looking the source code for Apple's ABPresence sample application, I saw that kABPersonFlags returns an NSNumber. Fortunately my sample code works unchanged thanks to the dynamic nature of Objective-C.

Monday, December 15, 2008

Financial realities of the App Store

David Barnard of AppCubby posted a very interesting response to Craig Hockenberry's "Ringtone apps" open letter entitled "Financial Realities of the App Store". David explores marketing challenges facing iPhone app developers and illustrates his points with lots of real world sales data from his own products. It's a fascinating soul baring glimpse into the challenges of bootstrapping a business.

Friday, December 12, 2008

ABPerson flags

Mac OS X provides an API for reading and writing to the built in Address Book, but the documentation doesn't spell everything out as clearly as it should. Take the ABPerson Class Reference for example.

ABPerson actually represents any kind of contact in Address Book. A flag is used to determine if an ABPerson object represents a person or a company. Checking that flag should be simple, but the docs left me mystified at first.

ABPerson is basically an associative array, which makes it flexible and extensible. You read most properties of an ABPerson using the valueForProperty: method (defined in base class ABRecord). valueForProperty: takes an NSString* property name and returns the property value as an id (an untyped object pointer in Objective-C). The exact type returned by valueForProperty: varies depending on the property. The standard property names are defined in the Constants section for ABPerson. Unfortunately, the entry for kABPersonFlags property neglects to mention the return type.

Turns out that the kABPersonFlags property is an NSString* NSNumber* that contains an integer. The integer is used as a classic bit field; the second table in the ABPerson Constants section shows the bit mask constants used to read the individual flags in kABPersonFlags.

I whipped up a small Properties category for ABPerson to simplify reading the show as company or person flags:
// file "ABPerson+Properties.h"

#import <AddressBook/ABPerson.h>


@interface ABPerson (Properties)

-(int) flags;
-(BOOL) showAsCompany;
-(BOOL) showAsPerson;

@end

And the module file:
// file "ABPerson+Properties.m"


#import "ABPerson+Properties.h"
#import <AddressBook/ABGlobals.h>


@implementation ABPerson (Properties)

-(int) flags {
return [[self valueForProperty: kABPersonFlags] intValue];
}

-(BOOL) showAsCompany {
return (self.flags & kABShowAsMask) == kABShowAsCompany;
}

-(BOOL) showAsPerson {
return (self.flags & kABShowAsMask) == kABShowAsPerson;
}

@end
The flags method gets the kABPersonFlags property value and converts it to an integer while showAsCompany and showAsPerson do the bitmasking and comparisons.

Thursday, December 11, 2008

Mac OS X talk by Jordan Hubbard

Jordan is Apple's Unix guru. He gave a recent talk about OS X past, present and future and touched on the iPhone and mobile computing near the end:
  • Ubiquitous computing is not “coming”, it is
    already HERE
  • Small devices under increasing pressure to
    become “micro” devices (active badges,
    bluetooth headsets, cerebral implants, etc)
  • Start thinking in terms of milliwatts, not just
    watts, because your power budget is
    shrinking
There's a longer overview at The Apple Core. Slides from the presentation are at http://www.usenix.org/events/lisa08/tech/hubbard_talk.pdf. (Note: the mysterious acronym LWMLAF stands for "Level Windows Makes Laughable Attempts at Following".)

Wednesday, December 10, 2008

Ringtone Apps

Craig Hockenberry of Iconfactory posted an open letter to Steve Jobs bemoaning the trend towards "ringtone apps":
"We have a lot of great ideas for iPhone applications. Unfortunately, we’re not working on the cooler (and more complex) ideas. Instead, we’re working on 99¢ titles that have a limited lifespan and broad appeal. Market conditions make ringtone apps most appealing."
He adds some interesting details of the economics of iPhone app development. The complete letter is at http://furbo.org/2008/12/09/ring-tone-apps/

Tuesday, December 9, 2008

UrlEncoding category for NSDictionary class

I've been writing some Objective-C code that builds URLs with long query strings. Since query strings are almost always associative arrays, I whipped up a simple category for the NSDictionary class.

A category is the Objective-C mechanism for adding additional methods to an existing class. To a C++ programmer, it's like being able to append more virtual methods to a class's vtable. C# has a similar facility called extension methods, and there are proposals to add this to Java. Of course, this is no big deal for scripting languages like Ruby, Python or JavaScript, but I like how Objective-C handles this.

For one thing, Objective-C forces you to name your category; this helps a lot in thinking and talking about a set of additional methods. For another, since the category declaration syntax resembles class declaration syntax, you naturally want to place it in its own pair of .h and .m files, like a class. Apple recommends a naming convention of class+category.h/m, which seems pretty reasonable.

So here's the header file for my UrlEncoding category for NSDictionary:
// file "NSDictionary+UrlEncoding.h"

#import <cocoa/cocoa.h>


@interface NSDictionary (UrlEncoding)

-(NSString*) urlEncodedString;

@end


And here's the module file:
// file "NSDictionary+UrlEncoding.m"

#import "NSDictionary+UrlEncoding.h"


// helper function: get the string form of any object
static NSString *toString(id object) {
return [NSString stringWithFormat: @"%@", object];
}

// helper function: get the url encoded string form of any object
static NSString *urlEncode(id object) {
NSString *string = toString(object);
return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
}


@implementation NSDictionary (UrlEncoding)

-(NSString*) urlEncodedString {
NSMutableArray *parts = [NSMutableArray array];
for (id key in self) {
id value = [self objectForKey: key];
NSString *part = [NSString stringWithFormat: @"%@=%@", urlEncode(key), urlEncode(value)];
[parts addObject: part];
}
return [parts componentsJoinedByString: @"&"];
}

@end

The code is pretty simple. Iterate over the keys in the dictionary and build an array of URL encoded "name=value" parts, then join the parts together with ampersands. The urlEncodedString method will handle keys and values of any class as long it has a reasonable description method. The code assumed that you never want a name/key to appear more than once in the query string, which is the most common case.