What am I doing ?
Does this code work in other places ?
The application is full of online requests and I have never had this problem in other view controllers. If the internet is not available, it shows a nice little message describing the state.
Where does the error occur
App Delegate
Error
* * * -[ReachabilityController respondsToSelector:]: message sent to deallocated instance 0x12a71320
The ReachabilityController shows a UIAlertView describing the state of error. The Alert view appears for abt a second and then the app crashes.
Debuging and Instruments ?
The NSLog(@"%p", reachability); logs same adress as in the error. 0x12a71320. It goes without saying that this adress varies on every run.
The Zombies template in Instruments also points out at Reachability Controller.
The white patch for 4 rows in "Responsible" section in the image below contains name of the App.
What I am expecting ?
Honestly, I don't have a clue as in the reason behind this behavior. I am sure it has to be very basic.
Do I have to declare a property to retain "ReachabilityController" as compared to local declaration now ?
Code
The fragment where crash occurs.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://myUrl"]];
NSData *authResponse = [NSData dataWithContentsOfURL:url];
dispatch_sync(dispatch_get_main_queue(), ^{
if(authResponse == nil) {
ReachabilityController *reachability = [[ReachabilityController alloc] init];
NSLog(@"%p", reachability);
[reachability checkReachability];
NSLog(@"%p", reachability);
return; // app crashes round here
}
}
ReachabilityController.h
#import <UIKit/UIKit.h>
#import "Reachability.h"
@interface ReachabilityController : UIViewController
-(void) checkReachability ;
@end
ReachabilityController.m
#import "ReachabilityController.h"
@interface ReachabilityController ()
@end
@implementation ReachabilityController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
-(void) checkReachability {
Reachability* internetAvailable = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [internetAvailable currentReachabilityStatus];
NSString *messageText;
if (netStatus == NotReachable)
{
messageText = [NSString stringWithFormat:@"iRestaurant has determined that internet access is not available at the moment"];
} else {
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
NSString *ipAdress = [infoDict objectForKey:@"LookUpIpAdress"];
NSString *host = [NSString stringWithFormat:@"%@/iRestaurant", ipAdress];
Reachability *netReach = [Reachability reachabilityWithHostName:host];
NetworkStatus hostStatus = [netReach currentReachabilityStatus];
if (hostStatus == NotReachable)
{
messageText = [NSString stringWithFormat:@"Sorry, for your inconvenience. iRestaurant server is currently unreachable. The iRestaurant server may be down for maintenance. Please check back after 5 mins"];
} else {
messageText = [NSString stringWithFormat:@"Sorry, for your inconvenience. This service is temporarily unavailable. We are working very hard to get it back on track."];
}
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"iRestaurant"
message:messageText
delegate:self
cancelButtonTitle:@"Done"
otherButtonTitles:nil];
[alertView show];
}
@end
UPDATE:
change question's title
Just a recent discovery. There are 3 instances where a data is requested from online server. As the internet is not available, all three methods almost request Reachability test at the same time. All three methods have method declaration something similar to the one above. All three methods use "local declaration" shown below to trigger the test.
ReachabilityController *reachability = [ReachabilityController alloc] init];
[reachability checkReachability];
You set the delegate for the UIAlertView to self. Unless you have a way to retain your ReachabilityController until the UIAlertView is released, this is a dangling reference.
Do you need the UIAlertView to interact with your ReachabilityController? It might be simplest to just pass nil as the delegate.