Tuesday, December 23, 2008
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.
Turns out that the
I whipped up a small
And the module file:
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; } @endThe
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:
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".)
- 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
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
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
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.
.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
And here's the module file:
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
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.
Subscribe to:
Posts (Atom)