Monday, October 12, 2009

Who wrote this crap?

It never ceases to amaze me how code that is written 2 or 3 months ago almost always ends up being crap.  I am exaggerating of course, but a lot of time the code I write when I revisit later is just crazy. 

I'm sure part of that is because the code I write on my own is often done at 2 or 3 in the morning.  It is interesting though, I can clearly see where the coding sessions were broken up instead of flowing smoothly in one session.


So, CoreLocation is one of the frameworks in the iPhone SDK.  I used it quite a bit with the LifeAware iPhone app and am using it again for my current project.  In both project I ran into the cached location issue.  Now if you read the SDK and even look at the sample code for this framwork you will see things like this:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    [locationMeasurements addObject:newLocation];
    // test the age of the location measurement to determine i
f the measurement is cached
    // in most cases you will not want to rely on cached measurements
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
    if (locationAge > 5.0) return;

This code does not seem to work.  I tried so many variations and it just doesn't work.  I'm sure it worked for Apple and maybe it works for you.  If so that's great, good for you.  But for me it didn't work so here is how I did it.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSLog(@"Found a new location %@",  newLocation);
    NSDate *now = [[NSDate alloc] init];
    NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
    [outputFormatter setDateFormat:@"HH:mm EEEE MMMM d"];
    NSString *nowTimeString = [outputFormatter stringFromDate:now];
    NSString *locationTimeString = [outputFormatter stringFromDate:newLocation.timestamp];
    NSLog(@"The age of the location is: %@", nowTimeString);
    NSLog(@"The age of the location is: %@", locationTimeString);
    if ([nowTimeString compare:locationTimeString] == NSOrderedSame){

Basically I take the timestamp from the location object and create a new one for "now".  Convert the two to string representations and compare the strings for equality.  This gives me a location that is less than a minute old. It seems just a little bit hackish but I think it's a pretty decent solution to a flaw in the API, seriously why wouldn't you say something like:

[locationManager startUpdatingLocation useCached:NO];

Happy coding!

-Aaron

1 comment:

Anonymous said...

if ([nowTimeString compare:locationTimeString] == NSOrderedSame)
should be written as
if ([nowTimeString isEqualToString:locationTimeString])