1

I'm in the process of trying to create a singleton class for weather functions (all encompassed) so that I can change/update/recall weather data throughout my entire app in a single allocated object.

I have it working except for one little weird bug. I'm using MKReverseGeocoder on devices running iOS < 5. CLGeocoder works fine on iOS 5+. Basically, this is what happens in the app:

In the app delegate, at launch, I create the shared instance of my weather singleton. This instance doesn't do anything unless there is a UIView that expects to report weather results. When a view that reports weather is loaded, if the location isn't already statically set in the preferences, the app attempts to pull your current location.

This works, and I can log the coordinates of the devices current location. After that is done, I immediately go into trying to reverse geolocate those coordinates. The method MKReverseGeocoder start does get executed and I can log that the instance's isQuerying property is true, so I know it's attempting to geolocate the coords. (Yes, I set the delegate as my shared instance and the instance is of type MKReverseGeocoderDelegate).

Now this is the weird part. If I am launching the app for the first time, and I add a weather UIView to the screen for the first time, MKReverseGeocoder starts but never calls the delegate method. If I then close the app and open it again (second time), the current location get's looked up, and MKReverseGeocoder does call the delegate methods and everything works. It just doesn't want to work on the first launch, no matter how many times I call it (I have a button that can initiate the lookup).

It's totally baffling. The iOS 5 CLGeocoder works fine on initial launch and every subsequent launch. the MKReverseGeocoder does not work (because it doesn't call the delegate methods) on initial launch, but does on subsequent launches.

Below is the relevant code:

-(void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error{

    NSLog(@"error getting location:%@", error);
    self.reverseGeocoder = nil;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"errorGettingLocation" object:nil userInfo:[NSDictionary dictionaryWithObject:error forKey:@"error"]];

}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)pm
{
    //update placemark and get weather from correct placemark
    placemark = pm;
    NSLog(@"singleton placemark: %@",placemark);
    [self getLocationFromPlacemark];
    self.reverseGeocoder = nil;
}


- (void) getReverseGeoCode:(CLLocation *)newLocation
{
    NSLog(@"reversGeocode starting for location: %@", newLocation);
    NSString *ver = [[UIDevice currentDevice] systemVersion];
    float ver_float = [ver floatValue];
    if (ver_float < 5.0) {
        //reverseGeocoder = nil;
        self.reverseGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
        self.reverseGeocoder.delegate = self;
        [self.reverseGeocoder start];
        if(self.reverseGeocoder.isQuerying){
            NSLog(@"self.reverseGeocoder querying");
            NSLog(@"self.reverseGeocoder delegate %@", self.reverseGeocoder.delegate);
            NSLog(@"self %@", self);
        }else {
            NSLog(@"geocoder not querying");
        }
    }
    else {
        [reverseGeocoder5 reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error){


            if([placemarks count]>0){
                placemark = [placemarks objectAtIndex:0];
                [self getLocationFromPlacemark];
            }
            else{
                if (error) {
                    NSLog(@"error reverseGeocode: %@",[error localizedDescription]);

                }
            }
        }];

    }
}

Also, I am setting reverserGeocoder as a (nonatomic, strong) property and synthesizing it. Remember, this works fine after a clean launch the second time (when there is a weather UIView already loaded). The calls to log aren't even getting hit (which is why I'm assuming the delegate methods aren't getting hit).

Any input would be GREATLY appreciated! Thanks!

dcinzona
  • 477
  • 2
  • 14

2 Answers2

1

I ended up figuring this out... well, kind of. Instead of using MKReverseGeocoder, I'm just doing a static lookup to google maps ala How to deal with MKReverseGeocoder / PBHTTPStatusCode=503 errors in iOS 4.3?

Works perfectly.

Community
  • 1
  • 1
dcinzona
  • 477
  • 2
  • 14
0

MKReverseGeocoder doesn't exist anymore... in iOS 5 You have to import CoreLocation and use CLGeocoder. Below is just some example sample code :

                  CLGeocoder *geoCoder = [[CLGeocoder alloc] init];
        CLLocation *location = [[CLLocation alloc] initWithLatitude:37.33188 longitude:-122.029497];

        [geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemark, NSError *error) {
            CLPlacemark *place = [placemark objectAtIndex:0];
            if (error) {
                NSLog(@"fail %@", error);

            } else {
                NSLog(@"return %@", place.addressDictionary);
            }

        }];
MCKapur
  • 9,127
  • 9
  • 58
  • 101
  • Correct, except on devices running iOS < 5 as stated in the original question... Basically, you end up having to use both methods if you want your app to run on older iOS versions...which was my problem. – dcinzona Jun 06 '12 at 02:09