I'm using the Reachability classes for checking when I got an internet connection en when it goes down.
This is my code:
IN VIEW DID LOAD:
internetReachable = [Reachability reachabilityForInternetConnection];
[internetReachable startNotifier];
// check if a pathway to a random host exists
hostReachable = [Reachability reachabilityWithHostname:#"www.google.com"];
[hostReachable startNotifier];
Then the notification method
-(void) checkNetworkStatus:(NSNotification *)notice
{
// called after network status changes
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
NSLog(#"The internet is down. IN AGENDA");
self.internetActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(#"The internet is working via WIFI.IN AGENDA");
self.internetActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(#"The internet is working via WWAN.IN AGENDA");
self.internetActive = YES;
break;
}
}
NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
switch (hostStatus)
{
case NotReachable:
{
NSLog(#"A gateway to the host server is down.IN AGENDA");
self.hostActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(#"A gateway to the host server is working via WIFI.IN AGENDA");
self.hostActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(#"A gateway to the host server is working via WWAN.IN AGENDA");
self.hostActive = YES;
break;
}
}
}
And finally how I add en remove the observer
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
}
-(void)viewDidDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];
}
THE PROBLEM
It seems like that the viewcontroller gets the notification multiple times.
This is my NSLOG
2014-01-04 10:32:16.299 Adsolut[10009:333b] CALLED reachabilityChanged
2014-01-04 10:32:16.299 Adsolut[10009:470b] CALLED reachabilityChanged
2014-01-04 10:32:16.300 Adsolut[10009:70b] The internet is down. IN AGENDA
2014-01-04 10:32:16.301 Adsolut[10009:70b] A gateway to the host server is down.IN AGENDA
2014-01-04 10:32:16.301 Adsolut[10009:70b] The internet is down. IN AGENDA
2014-01-04 10:32:16.302 Adsolut[10009:70b] A gateway to the host server is down.IN AGENDA
2014-01-04 10:32:16.313 Adsolut[10009:470b] CALLED reachabilityChanged
2014-01-04 10:32:16.313 Adsolut[10009:4a03] CALLED reachabilityChanged
2014-01-04 10:32:16.314 Adsolut[10009:70b] The internet is working via WIFI.IN AGENDA
2014-01-04 10:32:16.314 Adsolut[10009:333b] CALLED reachabilityChanged
2014-01-04 10:32:16.315 Adsolut[10009:70b] A gateway to the host server is down.IN AGENDA
2014-01-04 10:32:16.314 Adsolut[10009:f63] CALLED reachabilityChanged
2014-01-04 10:32:16.315 Adsolut[10009:70b] The internet is working via WIFI.IN AGENDA
2014-01-04 10:32:16.316 Adsolut[10009:70b] A gateway to the host server is down.IN AGENDA
2014-01-04 10:32:16.316 Adsolut[10009:70b] The internet is working via WIFI.IN AGENDA
2014-01-04 10:32:16.317 Adsolut[10009:70b] A gateway to the host server is down.IN AGENDA
2014-01-04 10:32:16.317 Adsolut[10009:70b] The internet is working via WIFI.IN AGENDA
2014-01-04 10:32:16.318 Adsolut[10009:70b] A gateway to the host server is down.IN AGENDA
Can somebody help ?
Add the reachability notification in the appdelegate didFinishLaunchingWithOptions only and set the value of reachability in Bool variable isInternetAvailable in appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(checkNetworkStatus:)
name:kReachabilityChangedNotification object:nil];
}
- (void)checkNetworkStatus:(NSNotification *)notice {
// called after network status changes
NetworkStatus internetStatus = [self.internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
//#######NSLog(#"The internet is down.");
self.isInternetAvailable = FALSE;
break;
}
case ReachableViaWiFi:
{
//#######NSLog(#"The internet is working via WIFI");
self.isInternetAvailable = TRUE;
break;
}
case ReachableViaWWAN:
{
//#######NSLog(#"The internet is working via WWAN!");
self.isInternetAvailable = TRUE;
break;
}
default:
{
//#######NSLog(#"The internet is working via mobile SIM!");
self.isInternetAvailable = FALSE;
break;
}
}
}
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 one problem - i need to check really internet connection. What i do now? Now i use Reachability class to check if is internet connection, but my app go to crash in this case: I've connected to the wifi in airport, it's was free wi fi but if i am not registred i can't surf. But Reachability thinkin that i've internet connection.How i use Reachability now?
if(self.internetReachableFoo.isReachable)
{
// We have internet
}
else
{
//we have no internet
}
So my question is, how i can use Reachability or other tools to check real internet connection?
thanks.
I you wan't to check internet connectivity then you can use reachability block
Reachability *reachability = [Reachability reachabilityWithHostname:#"www.google.com"];
reachability.reachableBlock = ^(Reachability *reachability) {
NSLog(#"Network is reachable.");
};
reachability.unreachableBlock = ^(Reachability *reachability) {
NSLog(#"Network is unreachable.");
};
// Start Monitoring
[reachability startNotifier];
You could attempt to connect to services you know will always be available, such as Google's public DNS servers. A simple ping will suffice.
I'm using this solution:
#implementation SomeClass{
Reachability* hostReachable;
}
Add this to your viewDidLoad method
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
hostReachable = [Reachability reachabilityWithHostName:#"www.apple.com"];
[hostReachable startNotifier];
And this method:
-(void) checkNetworkStatus:(NSNotification *)notice
{
NetworkStatus hostStatus = [self.hostReachable currentReachabilityStatus];
switch (hostStatus)
{
case NotReachable:
{
NSLog(#"NotReachable");
break;
}
case ReachableViaWiFi:
{
NSLog(#"ReachableViaWiFi");
break;
}
case ReachableViaWWAN:
{
NSLog(#"ReachableViaWWAN");
break;
}
}
}
I am calling a web service Synchronously using AFNetowrking. For example i am uploading some data to server and while uploading the wifi is out. How would i know that wifi is unavailable and cancel the request?
I don't know that you have used Reachability class or not. But if not used than it is given in below Apple sample code.
Reachability Introduction
Include these class in your project. Now with the help of AppDelegate.m file you can track availability of network.
Add notification observer in didFinishLaunchingWithOptions: method. This will notify on network changes.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityDidChange:) name:kReachabilityChangedNotification object:nil];
}
The notification method will call when there is any change in host connectivity or network connectivity.
- (void)reachabilityDidChange:(NSNotification *)notification {
Reachability *reachability = (Reachability *)[notification object];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
switch (internetStatus) {
case NotReachable: {
NSLog(#"The internet is down.");
break;
}
case ReachableViaWiFi: {
NSLog(#"The internet is working via WIFI.");
break;
}
case ReachableViaWWAN: {
NSLog(#"The internet is working via WWAN.");
break;
}
}
NetworkStatus hostStatus = [reachability currentReachabilityStatus];
switch (hostStatus) {
case NotReachable: {
NSLog(#"A gateway to the host server is down.");
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;
}
}
}
Cancel NSURLConnection request when you lost connectivity.
To cancel on going request use - (void)cancel; method of NSURLConnection.
What about retrying request until WiFi if alive again?
Try this cocoapod: https://github.com/shaioz/AFNetworking-AutoRetry
I want to trigger an action once the connection is available. There are solutions available which allows manually checking internet connection. One way i find is using NSTimer to check for internet connection during fixed intervals. But is it the most effective way to check for it? if Not, What is the right solution for this?
Here how you can register the observer and listen to it, Your application will be listening to kReachabilityChangedNotification & prompt you whenever status of network changes.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityHasChanged:) name:kReachabilityChangedNotification object:nil];
internetReachable = [[Reachability reachabilityForInternetConnection] retain];
[internetReachable startNotifier];
-(void) reachabilityHasChanged:(NSNotification *)notice
{
// called after network status changes
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
NSLog(#"The internet is down.");
break;
}
case ReachableViaWiFi:
{
NSLog(#"The internet is working via WIFI.");
break;
}
case ReachableViaWWAN:
{
NSLog(#"The internet is working via WWAN.");
break;
}
}
}
Check reachability code provided by apple.In appdelegate.m you can see this method.It will notify the network change.Work on it
//Called by Reachability whenever status changes.
- (void) reachabilityChanged: (NSNotification* )note
{
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
[self updateInterfaceWithReachability: curReach];
}
This case (NSLog(#"A gateway to the host server is down.");
is always running from some reason.
I'm using Apple Reachability class behind the scene.
I tried to insert other hosts but no luck please help.
Thanks in advance.
Here is the code
#implementation ConnectionManager
#synthesize internetActive, hostActive;
-(id)init {
self = [super init];
if(self) {
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkNetworkStatus:) name:#"NetworkReachabilityChangedNotification" object:nil];
internetReachable = [Reachability reachabilityForInternetConnection];
[internetReachable startNotifier];
hostReachable = [Reachability reachabilityWithHostName:#"www.google.com"];
[hostReachable startNotifier];
return self;
}
- (void) checkNetworkStatus:(NSNotification *)notice
{
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
NSLog(#"The internet is down.");
self.internetActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(#"The internet is working via WIFI.");
self.internetActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(#"The internet is working via WWAN.");
self.internetActive = YES;
break;
}
}
NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
switch (hostStatus)
{
case NotReachable:
{
NSLog(#"A gateway to the host server is down.");
self.hostActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(#"A gateway to the host server is working via WIFI.");
self.hostActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(#"A gateway to the host server is working via WWAN.");
self.hostActive = YES;
break;
}
}
}
Since you haven't mentioned about internetReachable showing the same error, I am assuming that you are able to connect to internet and that part is working fine. For the hostReachable part, you can try to change it as:
Change
[Reachability reachabilityWithHostName:#"www.google.com"];
to
[Reachability reachabilityWithHostName:#"http://www.google.com"];