0

My App was working perfectly well until I incorporated the Reachability .h and .m files to it to check for internet connectivity. While for the most part everything still runs perfectly well (all web pages load correctly, and when I purposefully turn-off my Airport to test things, Reachability catches it gracefully) - I do now get inexplicable crashes at odd times, with the dreaded "Exc-Bad-Access" error... I ran Instruments and found the Zombie - see screen-grab: Note the RefCt column - the count reached 20!

Looking at the "RefCt" column, you can see it reaches 15 - and I've seen it go higher than 20! In the "Responsible Caller" column (far right), I see all sorts of methods that I don't recognize - and who's call I certainly didn't initiate -- I'm assuming they're called by the system internally during run-time?

Either way, I followed Apple's Reachability code & instructions very carefully, as well as the tips from this very highly-ranked stackoverflow thread: How to check for an active Internet connection on iOS or OSX?

But I'm still getting these inexplicable crashes.

Can anyone offer any advice?

Here's the code:

#import "Reachability.h"


-(void) viewWillAppear:(BOOL)animated
{
   // check for internet connection
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];

internetReachable = [[Reachability reachabilityForInternetConnection] retain];
[internetReachable startNotifier];

// check if a pathway to a random host exists
hostReachable = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
[hostReachable startNotifier];

// now patiently wait for the notification
}



-(void) viewDidLoad {

    url = [NSURL URLWithString: @"http://www.google.com"];
    NSURLRequest *req = [NSURLRequest requestWithURL: url];
    [webPageView loadRequest:req];
    [super viewDidLoad];
}



-(void) checkNetworkStatus:(NSNotification *)notice
{
        // called after network status changes

    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];

    switch (internetStatus) 
    {
        case NotReachable:
        {
            [self displayMessageWithTitle:@"ERROR"
                               andMessage:@"Unable To Connect to Internet"
                              andOKButton:@"OK"];
            [self dismissModalViewControllerAnimated:YES];
            break;

        }
        case ReachableViaWiFi:
        {
            NSLog(@"The internet is working via WIFI.");

            break;

        }
        case ReachableViaWWAN:
        {
            NSLog(@"The internet is working via WWAN.");

            break;

        }
    }

    NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
    switch (hostStatus)
    {
        case NotReachable:
        {
            // NSLog(@"A gateway to the host server is down.");

            [self displayMessageWithTitle:@"ERROR"
                               andMessage:@"Host Not Reachable"
                              andOKButton:@"OK"];
            [self dismissModalViewControllerAnimated:YES];
            break;

        }

        case ReachableViaWiFi:
        {
            NSLog(@"A gateway to the host server is working via WIFI.");

            break;

        }

        case ReachableViaWWAN:
        {
            NSLog(@"A gateway to the host server is working via WWAN.");

            break;

        }
    }
}



- (void)webViewDidStartLoad:(UIWebView *)webView {
    [activityIndicator startAnimating];
}


- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [activityIndicator stopAnimating];
}


// Since this ViewController is presented Modally, this method removes it 
// via a button click:
-(IBAction) dismissWebTixView:(id)sender {
    [self dismissModalViewControllerAnimated:YES];
}




-(void) viewWillDisappear:(BOOL)animated {
    NSLog(@"In webForTix's 'viewWillDisappear' method....");
    [[NSNotificationCenter defaultCenter] removeObserver:self
name:kReachabilityChangedNotification
                                              object:nil];
}


// Was told it might be good to put "removeObserver" here and not in viewWillDisappear
// well neither worked - the App still crashes....
- (void)dealloc
{
    //NSLog(@"In webForTix's dealloc method....");
//    [[NSNotificationCenter defaultCenter] removeObserver:self
//                                                        name:kReachabilityChangedNotification
//                                                  object:nil];
NSLog(@"In webForTix's dealloc method - removedObserver...");
[super dealloc];

}

Community
  • 1
  • 1
sirab333
  • 3,662
  • 8
  • 41
  • 54
  • Do you implement `-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType`? When do you call `[reachabilityName stopNotifier]`? When do you `release` the Reachability objects you explicitly retain in `viewWillAppear`? – NJones Dec 03 '11 at 02:33
  • @NJones - no, I didn't implement 'webView: shouldStartLoadWithRequest: ' -- I'm not familiar with it. How should I be implementing it here? What should I be asking it to do, specifically in terms of relating to the Reachability objects/methods? As for '[reachabilityName stopNotifier]' - didn't call that either - not familiar with it. Its my 1st. time using Reachability & its methods. Can shed any light on how to implement these methods? Specific code examples are always best (Not just for my sake, but for future references of other users.) Thanks in advance! – sirab333 Dec 03 '11 at 04:56
  • @NJones -- having looked everything over so far, it seems possible that the crash-problems may have not originated with the Reachability methods. To test things out, I commented them all out and opted instead to use the NSURLconnection class methods - specifically, the 'didFailWithError:' method to test for a connection - and the app STILL crashed. So it may be something entirely different. Will keep searching... – sirab333 Dec 03 '11 at 14:44

1 Answers1

2

You have to carefully balance calls to addObserver and removeObserver.

If you add an observer for a notification in vieWillAppear, you need to remove it in viewWillDisappear.

If you add observer twice, you will get called twice for the same notification, and have to call removeObserver twice in order to get rid of both notifications.

I didn't see any obvious memory management problems. It looks like all the code you posted is creating auto-released objects, which should be fine.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • first off, many thanks for replying to this:-) Second, I'll double-check everything from top to bottom and look for imbalances/inconsistencies in the viewWillAppear/Disappear methods as pertaining to my handling of Notification observers. I will post what I discover here once (if) I discover anything. Thanks again for now, appreciate your input :-) – sirab333 Dec 03 '11 at 05:01
  • [I left this same comment for NJones in this here thread] having looked everything over so far, it seems possible that the crash-problems may have not originated with the Reachability methods. To test things out, I commented them all out and opted instead to use the NSURLconnection class methods - specifically, the 'didFailWithError:' method to test for a connection - and the app STILL crashed. So it may be something entirely different. Will keep searching... – sirab333 Dec 03 '11 at 14:45
  • @Duncan C. I have a couple of 'bones to pick' with your answer. While it is true that if you `addObserver:` twice you will get two notifications, I just ran a test and did remove both with one call to `removeObserver:`. Also, yes the Reachability objects are autoreleased but then they are wrapped in `retain`s and never released. – NJones Dec 03 '11 at 17:40
  • @everyone :-) Looks like there was nothing wrong with any of the Reachability stuff after all. The problem was with presenting a ModalViewController - which happened to also implement the Reachability code in it, and why I was thrown off as to the true nature of problem. Speaking of which... :-) Anyone know how to properly dismiss a ModalViewController? I'm using '[self.parentViewController dismissModalViewControllerAnimated:YES];' Problem is that the view which presented this modalVC was itself dismissed by the UINaviController which created IT... Make sense? any tips? – sirab333 Dec 03 '11 at 19:55