Saturday, September 11, 2010

CLLocation getDistanceFrom: vs distanceFromLocation:

In Backwards Compatibility if Apple Starts Polishing, Oliver Drobnik explains how he solved the getDistanceFrom: vs distanceFromLocation: problem. His solution involves a new method (distanceBetweenLocation:andLocation:) and eight lines of code for calling getDistanceFrom: through a NSInvocation.

Wouldn't it be nice if instead you could use [aLocation distanceFromLocation:anotherLocation] everywhere in your code, while still retaining backward compatibility? Enter the Objective-C runtime! In your main.m file, first #import <objc/runtime.h> and at the very beginning of your main function, add this:

Method getDistanceFrom = class_getInstanceMethod([CLLocation class], @selector(getDistanceFrom:));
class_addMethod([CLLocation class], @selector(distanceFromLocation:), method_getImplementation(getDistanceFrom), method_getTypeEncoding(getDistanceFrom));

Here you go, -[CLLocation distanceFromLocation:] available at runtime in any iOS version with only two lines of code. Note that on iOS 3, class_addMethod will add the distanceFromLocation: method to the CLLocation class using getDistanceFrom: implementation. On iOS 4, class_addMethod will do nothing as the method already exists.