InAppSettingsKit

July 15, 2010

Image courtesy of InAppSettingsKit.com

Image courtesy of InAppSettingsKit.com

I recently came across an extremely handy open source API for managing settings in iPhone apps. In a nutshell, InAppSettingsKit looks and works just like the normal settings/preferences mechanism (e.g., Settings.bundle), except that it allows you to easily display a settings view in your app in addition to the standard Settings.app (there are a few other perks, too).

In addition to their website, you can listen to a great interview with one of the creators from via the “mac developer network” website.

Update (8/19/10): It’s come to my attention that using delegates as the primary example below was not a good idea. When you have a @property for a delegate, the best practice is to use assign, not retain, so that you avoid a so-called “retain loop” and accompanying memory leaks (more info). That said, the idea of extending the NSObject protocol so that you can call release without warnings is still helpful in some situations–just not those involving delegates.

It’s pretty common to use custom Objective-C protocols in iPhone development, especially when it comes to using delegates to keep your code modular. Consider the following example:

@protocol EngineDelegate
{
    -(void) goFaster;
    -(void) goSlower;
}

@interface Automobile : NSObject
{
    id<EngineDelegate> engineDelegate;
}
@property (nonatomic, assign) id<EngineDelegate> engineDelegate;

This shows an Automobile class that has a single member variable/property, an “engine delegate” (i.e., the Automobile will delegate requests to go faster/slower to the EngineDelegate). Because engineDelegate is declared using the generic pointer “id” type, you can assign ANY object to it as long as that object implements the EngineDelegate protocol (i.e., has -goFaster and -goSlower methods). But what happens if you try to release the delegate? For example:

@implementation Automobile
...
- (void) dealloc
{
    [engineDelegate release];
}
@end

The compiler will generate a “-release not found” warning because it can’t tell if engineRelease implements the -release method. This is problematic not just because of the warning, but more importantly, because it prevents you from doing normal retain/release operations that are common in a managed memory environment like the iPhone. In other words, how are you supposed to ensure that the delegate is properly released?

I recently came across a clever solution to this dilemma on MobileOrchard. In a nutshell, the post suggests declaring protocols as inheriting from the NSObject protocol which, in turns, defines the retain and release methods. A lot of developers might be surprised to learn that you can do such a thing (I certainly was). Here’s what it looks like:

@protocol EngineDelegate <NSObject>
{
    -(void) goFaster;
    -(void) goSlower;
}

Now the Automobile class can safely assume that the delegate will implement the -retain and -release methods (and in most cases, the delegate will inherit the methods from the NSObject*). It’s nice that we can get rid of compiler warnings in this way, but it’s more important that we can use normal retain/release methods for memory management and not worry about whether or not the memory used by the delegate is freed.

*Note that not all objects extend the NSObject class (although for most folks, this is pretty rare). For example, many classes related to Cocoa’s “distributed object” mechanism descent from NSProxy instead of NSObject.

Colin Wheeler recently updated his chart of keyboard shortcuts for Xcode 3.2. Great resource.

xcodeshortcuts

Consider the following main() method which you’ll find in most iPhone applications:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

You might assume (as I did) that when an iPhone application ends, the above call to UIApplicationMain() will return and the rest of main() will run, eventually returning an integer. That assumption would be incorrect, however.

UIApplicationMain() never actually gets a chance to finish, nor do any of the statements that follow it have a chance to execute. When an iPhone OS application is closed (e.g., the user pushes the home button) the application is given a few seconds to run its -applicationWillTerminate method and then it calls the exit() system function. This makes sense, if you think about it: it’s more efficient to just stop the program and let the operating system free up all of its memory at once instead of running several individual -dealloc statements. Dump the whole trash bin instead of picking stuff out one-by-one, so to speak.

However, when I noticed this several months ago (while trying to run some logging and shut-down statements in main) I was very confused; the official Apple documentation for the UIApplicationMain() function said zilch about UIApplicationMain() never returning. In fact, while all the iPhone documentation obviously encouraged putting shutdown code inside the standard -applicationWillTerminate method, it said nothing about the fact that it’s essentially pointless to write any code after your call to UIApplicationMain() (aside from the return statement, necessary to keep the compiler happy).

After some collective head-scratching on developer forums someone observed that the documentation for NSApplicationMain()–the AppKit/Cocoa counterpart to UIApplicationMain()–did describe the exit(0) behavior. This prompted me to fill out a quick bug report requesting that Apple update the documentation. Fast-forward to today, when I randomly came across that documentation and noticed that it has been updated and my bug was closed. Who knows if I’m actually the one responsible for instigating the correction, but I’ll tell myself that I am.

Image used with permission from HD Digital Arts (www.hddigitalarts.com)

Image courtesy of: HD Digital Arts www.hddigitalarts.com

If you’re an iPhone developer you’ll inevitably need to work with images at some point. It’s extremely easy to load and display images in a variety of formats such as PNG, JPEG, etc. That said, the easy route isn’t always the most efficient; taking the time to learn how the iPhone handles images (e.g., storing each pixel with Blue/Green/Red/Alpha-ordered octets instead of Red/Green/Blue) and how to use that knowledge to your advantage is definitely a worthwhile investment.

For example, the official Apple documentation suggests that you use the PNG image format for iPhone graphics and briefly mentions that Xcode does some sort of “optimization” on each .png file during a device build. What does this mean? Just how much more efficient is one of these mysterious “optimized” PNG files? Who knows! Apple doesn’t tell us.

Fortunately Jeff LaMarche took the time to write up an excellent, short, easy-to-read yet thorough explanation regarding the iPhone, image formats, and PNG optimization (link). Personally I feel like this should be required reading for all new iPhone developers (and I wish I had found the article sooner!).