In my app delegate I have this:
Reachability* reach = [Reachability reachabilityWithHostname:#"www.google.com"];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
[reach startNotifier];
HomeViewController_iPhone *homeViewController = [[HomeViewController_iPhone alloc] initWithNibName:#"HomeViewController_iPhone" bundle:nil];
homeViewController.managedObjectContext = self.managedObjectContext;
UINavigationController *homeNavController = [[UINavigationController alloc] initWithRootViewController: homeViewController];
homeNavController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
self.tabBarController.viewControllers = [NSArray arrayWithObjects:homeNavController, nil];
...
-(void)reachabilityChanged:(NSNotification*)note
{
Reachability * reach = [note object];
if([reach isReachable])
{
NSLog(#"Notification Says Reachable");
self.isConnected = YES;
}
else
{
NSLog(#"Notification Says UN-Reachable");
self.isConnected = NO;
}
}
The problem is that in my HomeViewController (viewDidLoad) I do this:
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if (appDelegate.isConnected)
{
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL: kFeedURL];
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
});
}
But appDelegate.isConnected is always NO, even when I have a connection. I think the check is being made before the Reachability class establishes that there is a connection. But where to I make the call to fetch the data? I've tried viewDidLoad and viewWillAppear, but isConnected is still NO at both of those points.
Solved by doing this in the app delegate, before creating the view controllers, as in the answer suggested by dnstevenson.
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if (internetStatus != NotReachable) {
//my web-dependent code
}
else {
//there-is-no-connection warning
}
Related
I want my app to detect the internet connection loss automatically. So im using the following code.
- (void)applicationDidBecomeActive:(UIApplication *)application {
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable) {
[Settings hideSpinner];
//Show no internet connectivity dialog.
} else {
}
}
But the problem is that it is not checking the internet connectivity continually.
it checks only when the app has become active. How can I be able to check for internet connection continually throughout the app life cycle and throw an warning if internet goes off automatically?
Once your application has launched, you can fire a NSTimer to do the same:
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(checkForConnectivity)
userInfo:nil
repeats:YES];
}
-(void)checkForConnectivity {
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable) {
//No internet connectivity - perform required action
}
else {
//Internet connectivity is valid
}
}
Thanks!
Add obeserver like this in Reachability method.
1) [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
It will call automatically when your app open/in background mode and it call reachabilityChanged.
2) [[NSNotificationCenter defaultCenter] postNotificationName:#"ChangeInternetConnection" object:nil];
ChangeInternetConnection you have to add observer to your ViewController to get status when internet changing it's status.
- (void) checkInternetConnetion {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
//NSString *remoteHostName = #"www.apple.com";
self.internetReachability = [Reachability reachabilityForInternetConnection];
[self.internetReachability startNotifier];
[self updateInterfaceWithReachability:self.internetReachability];
}
#pragma mark - Reachability Methods
- (void)updateInterfaceWithReachability:(Reachability *)reachability {
if (reachability == self.internetReachability) {
[self checkStatus:reachability];
}
if (reachability == self.wifiReachability) {
[self checkStatus:reachability];
}
}
-(void)checkStatus :(Reachability *)reachability {
NetworkStatus netStatus = [reachability currentReachabilityStatus];
BOOL connectionRequired = [reachability connectionRequired];
NSString* statusString = #"";
switch (netStatus) {
case NotReachable: {
self.isInternetOn = FALSE;
break;
}
case ReachableViaWWAN: {
self.isInternetOn = TRUE;
break;
}
case ReachableViaWiFi: {
self.isInternetOn = TRUE;
break;
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"ChangeInternetConnection" object:nil];
}
- (void) reachabilityChanged:(NSNotification *)note {
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
[self updateInterfaceWithReachability:curReach];
}
Timer is not an efficient way to do this but you can also use timer too.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(handleConnectivity)
userInfo:nil
repeats:YES];
}
-(void)handleConnectivity
{
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable)
{
//No internet connectivity - perform required action
}
else
{
//Internet connectivity is valid
}
}
Best way is to use Reachability code. Check here for apple sample code. That has a lot of convenience methods to check internet availability, Wifi/WAN connectivity check etc..
For example:-
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(networkChanged:) name:kReachabilityChangedNotification object:nil];
reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];
- (void)networkChanged:(NSNotification *)notification
{
NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];
if(remoteHostStatus == NotReachable) { NSLog(#"not reachable");}
else if (remoteHostStatus == ReachableViaWiFiNetwork) { NSLog(#"wifi"); }
else if (remoteHostStatus == ReachableViaCarrierDataNetwork) { NSLog(#"carrier"); }
}
You can only check this things in background
*audio—The app plays audible content to the user while in the background. (This content includes streaming audio or video content
using AirPlay.)
*location—The app keeps users informed of their location, even while it is running in the background.
*voip—The app provides the ability for the user to make phone calls using an Internet connection.
*newsstand-content—The app is a Newsstand app that downloads and processes magazine or newspaper content in the background.
*external-accessory—The app works with a hardware accessory that needs to deliver updates on a regular schedule through the External
Accessory framework.
*bluetooth-central—The app works with a Bluetooth accessory that needs to deliver updates on a regular schedule through the Core Bluetooth
framework.
*bluetooth-peripheral—The app supports Bluetooth communication in peripheral mode through the Core Bluetooth framework.
Firstly import in your class: #import "Reachability.h"
Then do like following way:
add an observer for reachability change notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification object:nil];
-(BOOL)reachabilityChanged:(NSNotification*)note
{
BOOL status =YES;
NSLog(#"reachabilityChanged");
Reachability * reach = [note object];
if([reach isReachable])
{
status = YES;
NSLog(#"your network is Available");
}
else
{
status = NO;
//Do something here
}
return status;
}
Add a observer.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
-(BOOL)reachabilityChanged:(NSNotification*)note
{
BOOL status =YES;
NSLog(#"reachability is changed");
Reachability * reach = [note object];
if([reach isReachable])
{
status = YES;
NSLog(#"NetWork is Available. Please go ahead");
}
else
{
status = NO;
NSLog(#"NetWork is not Available. Please check your connection.");
}
return status;
}
You can make use of Reachability framework from iOS and combine it with NSTimer.
I have an issue with UIAlertView.
In my AppDelegate I check the reachability of the application:
If it is not reachable I call the alert from Utils class.
- (void)reachabilityChanged:(NSNotification *)note
{
Reachability* currentReachabilityObject = [note object];
NSParameterAssert([currentReachabilityObject isKindOfClass:[Reachability class]]);
NetworkStatus status = [currentReachabilityObject currentReachabilityStatus];
if (status == NotReachable)
{
[Utils showAlert:#"NotReachableNetwork") title:#"Error")];
}
}
And if I turn on/turn off Wi-Fi two-three times I get three alerts.
But I want to show only one.
Please tell me how to check is there any alerts on the screen from AppDelegate.
Why don't you keep a reference to the alert?
That way you just have to check if the alert is nil, if it is nil you can create a new alert. In case it isn't nil, it means you already have one showing and there's no need to show another. Easy as pie.
Please try below code and I think it will work for you.
#pragma mark - Internet Reachability Handlers -
- (void) updateInterfaceWithReachability: (Reachability*) curReach
{
NetworkStatus netStatus = [curReach currentReachabilityStatus];
if (_changeReachability)
{
if(netStatus==NotReachable)
{
[Utils showAlert:#"NotReachableNetwork") title:#"Error")];
_isNetAvailable = NO;
_changeReachability = NO;
}
else
{
_isNetAvailable = YES;
_changeReachability = NO;
}
}
}
//Called by Reachability whenever status changes.
- (void) reachabilityChanged: (NSNotification* )note
{
_changeReachability = YES;
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
[self updateInterfaceWithReachability: curReach];
}
-(void)checkallTypesofInternet
{
// For 3G Connection
hostReach = [Reachability reachabilityWithHostName:#"www.apple.com"];
[hostReach startNotifier];
[self updateInterfaceWithReachability: hostReach];
// For Individual Net Connection
internetReach = [Reachability reachabilityForInternetConnection];
[internetReach startNotifier];
[self updateInterfaceWithReachability: internetReach];
// For WiFi
wifiReach = [Reachability reachabilityForLocalWiFi];
[wifiReach startNotifier];
[self updateInterfaceWithReachability: wifiReach];
}
Let me know if you are still facing any issue.
I need a notification when device has WiFi connection is available or Device get connect via WiFi. I need to do some stuff only when WiFi is available.
I have used following code from Reachability:
BOOL status=true;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
internetReachability = [Reachability reachabilityForInternetConnection];
[internetReachability startNotifier];
NetworkStatus internetNetworkStatus = [internetReachability currentReachabilityStatus];
status = (internetNetworkStatus == ReachableViaWiFi);
But checkNetworkStatus: method not called properly and accurately. So, please guide me to solve this problem.
Any help to solve problem must be appreciated.
I hope it will help you in your problem.
-(void) rechabilityInit
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
self.internetConnectionReach = [Reachability reachabilityForInternetConnection];
self.internetConnectionReach.reachableBlock = ^(Reachability * reachability)
{
NSLog(#"%#", reachability.currentReachabilityString);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
dispatch_async(dispatch_get_main_queue(), ^{
// Do stuff here when WIFI is availble
}];
};
self.internetConnectionReach.unreachableBlock = ^(Reachability * reachability)
{
NSLog(#"%#", reachability.currentReachabilityString);
dispatch_async(dispatch_get_main_queue(), ^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// do some stuff here when WIFI not present
}];
};
[self.internetConnectionReach startNotifier];
}
-(void)reachabilityChanged:(NSNotification*)note
{
Reachability * reach = [note object];
if (reach == self.localWiFiReach)
{
if([reach isReachable])
{
NSString * temp = [NSString stringWithFormat:#"LocalWIFI Notification Says Reachable(%#)", reach.currentReachabilityString];
NSLog(#"%#", temp);
}
else
{
NSString * temp = [NSString stringWithFormat:#"LocalWIFI Notification Says Unreachable(%#)", reach.currentReachabilityString];
NSLog(#"%#", temp);
}
}
}
The following way is help me to solve my problem:
// Use below to any method
// check for internet connection
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
internetReachability = [Reachability reachabilityForInternetConnection];
[internetReachability startNotifier];
-(void) checkNetworkStatus:(NSNotification *)notice {
// called after network status changes
NetworkStatus internetStatus = [internetReachability currentReachabilityStatus];
switch (internetStatus) {
case NotReachable: {
NSLog(#"The internet is down.");
break;
}
case ReachableViaWiFi: {
NSLog(#"The internet is working via WIFI.");
//Remove Observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
//Write your code
break;
}
case ReachableViaWWAN: {
NSLog(#"The internet is working via WWAN.");
break;
}
}
}
We are developing a module, which checks whether the Internet connection either is active or not active or disabled. The previous scenarios work well, except the case if there is a WI-FI connection but the internet is not active. We have made sure that the data mobile connection (3G, 4G) is not enabled.
We have seen that everybody recommends using the Tony Million's Reachability class, which replaces the Apple's one.
Below, there is the code that we are using:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Reachability *reachability = [Reachability reachabilityWithHostname:#"www.google.com"]; //Cambiar por el servidor
reachability.reachableBlock = ^(Reachability *reachability) {
NSLog(#"Network is reachable.");
};
reachability.unreachableBlock = ^(Reachability *reachability) {
NSLog(#"Network is unreachable.");
};
// Start Monitoring
[reachability startNotifier];
return YES;
}
Whether there is a WI-FI connection but the internet is not active, it does not work because it goes to:
reachability.reachableBlock = ^(Reachability *reachability) {
NSLog(#"Network is reachable.");
}
instead of
reachability.unreachableBlock = ^(Reachability *reachability) {
NSLog(#"Network is unreachable.");
}
What we are missing?
Thank you in advance,
Regards
Try this one,
- (BOOL)isNetAvailable
{
BOOL isNetAvailable = NO;
Reachability *reach = [Reachability reachabilityWithHostName:#"www.google.com"];
NetworkStatus netStatus = [reach currentReachabilityStatus];
if (netStatus != NotReachable)
{
isNetAvailable = YES;
}
else
{
isNetAvailable = NO;
}
return isNetAvailable;
}
You can use :
NSURLRequest *nsrequest = [NSURLRequest requestWithURL:[NSURL URLWithString: #"http://www.google.com"]];
NSHTTPURLResponse *response = nil;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:nsrequest returningResponse:&response error:&error];
if(response.statusCode==0){
NSLog(#"Network is unreachable.");
}
else{
NSLog(#"Network is reachable.");
}
I have the following code in my viewController.m class:
- (void) testInternetConnection
{
internetConnection = [Reachability reachabilityWithHostname:#"www.google.com"];
// Internet is reachable
internetConnection.reachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Yayyy, we have the interwebs!");
});
};
// Internet is not reachable
internetConnection.unreachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Someone broke the internet :(");
});
};
[internetConnection startNotifier];
}
How do I use the startNotifier?
Do I have to put this in every view controller I want to test internet connectivity in?
I use this to test the status:
BOOL status = ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable);
startNotifier means after that any network state changed will notify whoever register the kReachabilityChangedNotification notification.
You don't have to put this in every view controller.
1、You need a singleton instance and has a member value which is used to keep network state.
2、Register the kReachabilityChangedNotification notification , handle it and get network state and store it in your member value and Post Notification(custom notificaiton) to notify others(your viewcontroller).
3、Provide interfaces to get the current network state so that your viewcontrollers will know the network state when network state changed.
Try this in your app delegate class.
write this code in application didFinishLaunchingWithOptions.
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil];
Reachability *hostReachable = [[Reachability reachabilityWithHostName: #"www.google.com"] retain];
[hostReachable startNotifier];
Write this methods in your Appdelegate class.
- (void) reachabilityChanged: (NSNotification* )note
{
Reachability* curReach = [note object];
[self updateInterfaceWithReachability: curReach];
}
- (void) updateInterfaceWithReachability: (Reachability*) curReach
{
if(curReach == hostReachable)
{
NetworkStatus netStatus = [curReach currentReachabilityStatus];
if (netStatus == 0 )
{
NSLog(#"offline");
}
else
{
NSLog(#"online");
}
}
}