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");
}
}
}
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 have a TableView that recieves data from a server and all works fine.
- (void)viewDidLoad
{
[super viewDidLoad];
// retrieveData is a method that Loads the Content
[self retrieveData];
}
But If the user has no internet, the app crashs.
How Can I check this connectivity for, if is Ok I load the data.. and If IS NOT OK, i send a NSAlert to the user?
You can check for internet connection as given below and hope you can implement UIAlertview on yours.
// Checks if we have an internet connection or not
- (void)testInternetConnection
{
internetReachableFoo = [Reachability reachabilityWithHostname:#"www.google.com"];
// Internet is reachable
internetReachableFoo.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
internetReachableFoo.unreachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Someone broke the internet :(");
});
};
[internetReachableFoo startNotifier];
}
This is well explained by iWasRobbed here.
Courtesy:- https://stackoverflow.com/a/3597085/1865424
Once you have downloaded and imported Reachbility.m and Reachbility.h files
create a helper function:
-(BOOL)IsConnected{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
return !(networkStatus == NotReachable);
}
Then use it
if([self IsConnected]){
[self retrieveData];
}
else{
//not connected to internet!
}
Do a google search for the "Reachability" class from Apple.
Make your code bullet proof enough so that it won't crash even if there is no internet.
I have a Boolean value to check Reachability with following code.
#property (nonatomic,assign) BOOL isOnline;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
Reachability * reach = [Reachability reachabilityWithHostname:#"www.google.com"];
reach.reachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Reachable");
self.isOnline = YES;
});
};
reach.unreachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
self.isOnline = NO;
NSLog(#"Unable");
});
};
[reach startNotifier];
However when i check it with
if(self.isOnline == YES)
{
NSLog(#"YES");
}
else{
NSLog(#"NO");
}
It's only showing NO. I am sure Reachability can reach to the internet and i have connection. However Boolean value is not set to YES.
How can i do it?
It seems that you are using the Reachability by Tony Million so 1st thing i would suggest is to use isReachable function in it.
Secondly, there is an issue with this reachability in iOS7 so to resolve this you have to do the following
In the Function -(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags in Reachability.m you have to commit one line
#if TARGET_OS_IPHONE
if(flags & kSCNetworkReachabilityFlagsIsWWAN)
{
// We're on 3G.
if(!self.reachableOnWWAN)
{
// We don't want to connect when on 3G.
// Comment this line
//connectionUP = NO;
}
}
#endif
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];
}