Thursday, April 12, 2012

ARC and Leaks: Great But Imperfect - Part 1

This week I spent time debugging yet another memory management bug. The exercise served as a not-so-friendly reminder that correct memory management remains a very difficult task even with technologies such as Automatic Reference Counting (ARC) and the Leaks Instrument.

Hopefully most Objective-C developers understand the main limitation of ARC: ARC can't break retain cycles. It is up to the programmer to prevent or break retain cycles. Luckily the Leaks Instrument is available to help since it can detect retain-cycle-memory-leaks.

With this in mind I generally develop my code in two stages:
  1. Develop the code using ARC and try my best not to introduce retain cycles.
  2. Run the code under the Leaks Instrument to find and break any retain cycles I might have accidentally introduced.

Once you are comfortable with these steps it is easy to gain a false sense of confidence in your memory management handling. We need to remember that Leaks, as good as it is, is not perfect. It does not (and can not) guarantee that it will find all memory leaks.

This week I was reminded of this fact when I noticed what appeared to be a retain-cycle-memory-leak in my code but which was not being reported under Leaks.

Below is a much simplified version of the code. The class is called LeakyViewController, it is a subclass of UIViewController, and it maintains a strong reference to itself which creates a simple retain-cycle.

If you create an instance of this class and immediately throw it away, the instance will never be deallocated and Leaks does not report a problem.

So what is the deal? I'll explore this further in parts 2 and 3 of this blog post series.

@interface LeakyViewController ()
@property (nonatomic, strong) NSObject *selfRef;
@end

@implementation LeakyViewController

@synthesize selfRef;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
NSLog(@"allocating a LeakyViewController");
self.selfRef = self;
}
return self;
}

- (void) dealloc {
NSLog(@"deallocating a LeakyViewController");
}

@end


Sunday, April 1, 2012

Android's NinePatch: Better Stretchable Images than iOS

A friend of mine this week told me about NinePatch, a nice image file format developed as part of Android.

A good overview of NinePatch can be found here. It is basically a PNG with extra information included to identify the "stretchable" areas of the image. Android then handles the resizing (and proper stretching) automatically for you.

This is great because it frees the programmer from having to write any code related to stretchable images.

It also adheres to the DRY principal (Don't Repeat Yourself) because all the image information is stored in one place: the image (where it belongs) instead of in two places (the image and the code). This allows a designer, for example, to update the image without requiring any software changes.

iOS doesn't yet have an equivalent to NinePatch but it turns out that there is an open source library that brings NinePatch support to iOS. Here is the announcement from the developer Tortuga 22.

In addition to code improvements another potential benefit to adopting NinePatch might be to increase the image asset reuse between your Android and iOS apps.

I haven't yet tried this myself but hope to soon.