views:

655

answers:

3

I am getting odd behavior from an NSAlert in two different parts of my program. The behavior is:

  1. Alert appears and then spontaneously disappears.
  2. Alert reappears and then remains until dismissed by user i.e. normal behavior.
  3. Alert reappears again.

This behavior only occurs the first time the method that displays the alert is called. After that first time, it behaves normally.

Here is the code for the one of the parts in which the behavior occurs:

UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:@"You are in the right place." message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [locationAlert show];
        [locationAlert release];

Or if you prefer, with a bit more context:

- (IBAction)locateMe {
NSLog(@"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation * )oldLocation {
if (newLocation.horizontalAccuracy >= 0) {

    CLLocation *airportLocation = [[[CLLocation alloc] initWithLatitude:51.500148 longitude:-0.204669] autorelease];
    CLLocationDistance delta = [airportLocation getDistanceFrom: newLocation];
    long miles = (delta * 0.000621371) + 0.5; //metres to rounded mile
    if (miles < 3) {
        UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:@"You are in the right place." message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [locationAlert show];
        [locationAlert release];
        [locMan stopUpdatingLocation];
    } else {
        UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:@"You are not in the right place." message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [locationAlert show];
        [locationAlert release];
        [locMan stopUpdatingLocation];

    }
}
}

- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:@"Error." message:error.code delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

[locationAlert show];
[locMan release];
locMan = nil;
}

Any ideas? Thanks.

Edit---------

The other place this happens is:

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSString * errorString = [NSString stringWithFormat:@"Unable to download feed from web site (Error code %i )", [parseError code]];
NSLog(@"error parsing XML: %@", errorString);

UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Error loading content" message:errorString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
}

For context the first case is in the AppDelegate and the second in the view controller for the 1st tab view. The second problem occurs every time the xml is reloaded when there is no internet connection. The first one only occurs the first time the function is called.

Edit-----

If I move the alert it works. Unfortunatly this is not where I want it!

- (IBAction)locateMe {

 UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:@"You are in the right place." message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[locationAlert show];
/*
NSLog(@"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];*/
}

Update:

I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.

I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.

Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:

[locationAlert show];
locationAlert = nil;

That way it works perfectly.

+2  A: 

You're not turning off your location manager when you first show the alert. As the location is refined by the device (ie, the accuracy is increased), your callback will be (potentially) called multiple times. You should use [locMan stopUpdatingLocation] after your alert display.

Ben Gottlieb
Thanks. I'll give that a go.
Nik1777
No dice. I put that in straight after [locationAlert release] and the behaviour hasn't changed.
Nik1777
I do also have the problem in a non-corelocation related part of my app. An error message if the online component can't be downloaded flashes up the same no. of times.
Nik1777
I think this would explain why the alert displayed numerous times but it would not explain why it spontaneously disappears.
TechZen
Nik1777 -- post the code you added in a comment and I will edit your question to reflect the changes. (time permitting)
TechZen
Thanks. I've edited the question to include the change (stopUpdatingLocation) and the other place where this happens. For context the location alert is in the AppDelegate and the XML one is in the view controller for the first tab.
Nik1777
to Ben Gottlieb: You were correct that the method was being called multiple times. The disappearances appear to be caused by the UIAlert effectively overwriting itself.
TechZen
Yes, when you show a UIAlert, if there's one already visible, it will appear to close and open the new one, then re-show the old one when the new one is dismissed.
Ben Gottlieb
A: 

I think the NSAlert disappearing on its own is the key to solving this.

It's simple to explain why an alert displays unexpectedly i.e. it's just been called unexpectedly. However, it's not so common to programmatically dismiss an alert. Whatever is causing it to disappear is most likely triggering the display again.

To debug I suggest:

(1) Looking in your code for the NSAlert – dismissWithClickedButtonIndex:animated: method and see if somehow you're actually dismissing the alert programmatically.

(2) I believe (someone double-check me on this) that an alert view is added as a subview to whichever base view is currently on screen. It might be that the base view is disappearing for some reason and taking the alert view with it. If the view disappears and then reappears rapidly enough, it might not be obvious when the alert is frontmost. (Edit: see Ed Marty's comment below.)

(3) Since this happens in two separate pieces of the app, compare both to find a common element or structure. That common element might be the cause. An odd problem.

Edit01: Updated for additional info

If locMan isan instance variable, it should be defined as a property and you should access it every time withself.locMan By accessing it directly, you lose your automatic retention management.

TechZen
Thanks.1. I don't remember using dismissWithClickedButtonIndex:animated anywhere and a search of the code directory doesn't return anything.2.I don't know how I can check for this.3. I can't find a common oddity but I have edited the post to include both bits of code so maybe you can see something.Thanks again.
Nik1777
See my edit for a possible explanation.
TechZen
Thanks. I was getting an error to that effect which I didn't understand when I compiled for the simulator. It didn't complain when I compiled for the device so I ignored it.
Nik1777
Heh, that one's bit me before. You should go into the project settings and set "treat warnings as errors" so that you have to stop and fix all your warnings. A warning is just an error that doesn't kill the build. All warnings will eventually cause problems so fix them as you go.
TechZen
As for (2), that's not correct. When an alert view is shown, it is shown in its own window layered on top of the main window.
Ed Marty
@Ed Marty - Thanks for the double check.
TechZen
A: 

I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.

I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.

Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:

[locationAlert show];
locationAlert = nil;

That way it works perfectly.

Nik1777