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.");
}
Related
I have added reachability into my project following things are working fine.
1.It Check successfully host request, wifi or mobile date active connection..
but i have tested the reachability of wifi with loss of internet connection , it may give the results like reachable via wifi...(example like you have active wifi connection but no internet received form wifi)
I did added NSTimers and achieved exact result, but i want to achieve the this thing by reachability so can anyone help to solve my issue...
i also had similar problem to detect if internet lost. example : you have connected to WIFI but internet is not active due to bill settlement or something.
If you are using AFNetworking there will be error code if you lost your internet connection while doing some POST request.
below is my code.
AFHTTPSessionManager * manager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:#"" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
//If response Sucess
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"Error %#",error);
if(error.code==-1009){
// This Error Comes when internet is not active.
so inside this you can make any action
}
}];
Here is my answer ,
I did not initialize timers just using completion blocks , but completion blocks with delay almost equal to NSTIMERS.
I have created api for reachability with all conditions..
just attach sample method to check the all conditions..
-(void) blocksWithReachabiltyCheck :(bool) r_Status
{
__weak id weakSelf = self;
callBack = ^{
double delayInSeconds = 10.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
id strongSelf = weakSelf;
if (!strongSelf) {
return;
}
// Schedule the timer again
//callBack();
[weakSelf targetMethod:r_Status];
});
};
// Start the timer for the first time
callBack();
}
-(void)targetMethod:(bool)sender
{
NSString *remoteHostName = #"www.apple.com";
// NSString *remoteHostLabelFormatString = NSLocalizedString(#"Remote Host: %#", #"Remote host label format string");
// self.remoteHostLabel.text = [NSString stringWithFormat:remoteHostLabelFormatString, remoteHostName];
// NSLog(#"%#",remoteHostLabelFormatString);
self.hostReachability = [Reachability reachabilityWithHostName:remoteHostName];
[self.hostReachability startNotifier];
self.internetReachability = [Reachability reachabilityForInternetConnection];
[self.internetReachability startNotifier];
self.wifiReachability = [Reachability reachabilityForLocalWiFi];
[self.wifiReachability startNotifier];
if (sender == YES)
{
callBack();
}
}
//stop timer
-(void) RXStopNotifier
{
[self blocksWithReachabiltyCheck:NO];
}
//start notifier with host name
-(void) RXStartNotifier:(NSString *)hostNameString
{
[self blocksWithReachabiltyCheck:YES];
hostName = hostNameString;
}
#synthesize callBack;
#property (copy)__block void (^callBack)(void) ;
//Notification method
- (void) RXSeachabilityChanged:(NSNotification *)note
{
if (timerFlag == false)
{
timerFlag = true;
Reachability* curReach = [note object];
NetworkStatus netStatus = [curReach currentReachabilityStatus];;
statusReach = 0;
switch (netStatus)
{
case NotReachable: {
NSLog(#"Not Access ");
statusReach = 0;
break;
}
case ReachableViaWWAN:
// {
// NSLog(#"Reachable WWAN");
// statusReach = 1;
// // imageView.image = [UIImage imageNamed:#"WWAN5.png"];
// break;
// }
case ReachableViaWiFi: {
if (instantFlag == NO)
{
NSLog(#"Reachable WIFI or Reachable WWAN");
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:hostName] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:1];
NSURLResponse *response = nil;
NSError *error = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//NSLog(#"response %d", [(NSHTTPURLResponse *)response statusCode]);
if ([(NSHTTPURLResponse *)response statusCode] == 200) {
statusReach = 1;
NSLog(#"Success");
}
else
{
statusReach = 2;
NSLog(#"Failed");
}
}
else
{
statusReach = 1;
}
break;
}
}
}
}
if any one having doubts just reach me....
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.
This question already has answers here:
How can I check for an active Internet connection on iOS or macOS?
(46 answers)
Closed 5 years ago.
I'm wondering how I can check if the user is connect to internet through WIFI or cellular data 3G or 4G.
Also I don't want to check if a website is reachable or not, the thing that I want to check if there is internet on the device or not. I tried to look over the internet all that I see is that they check if the website is reachable or not using the Rechability class.
I want to check if the user has internet or not when he opens my application.
I'm using Xcode6 with Objective-C.
Use this code and import Reachability.h file
if ([[Reachability reachabilityForInternetConnection]currentReachabilityStatus]==NotReachable)
{
//connection unavailable
}
else
{
//connection available
}
First Download Reachability classes from this Link:
Rechability from Github
Add Instance of Reachability in AppDelegate.h
#property (nonatomic) Reachability *hostReachability;
#property (nonatomic) Reachability *internetReachability;
#property (nonatomic) Reachability *wifiReachability;
Import Reachability in your AppDelegate and just copy and past this code in your Appdelegate.m
- (id)init
{
self = [super init];
if (self != nil)
{
//[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
NSString *remoteHostName = #"www.google.com";
self.hostReachability = [Reachability reachabilityWithHostName:remoteHostName];
[self.hostReachability startNotifier];
self.internetReachability = [Reachability reachabilityForInternetConnection];
[self.internetReachability startNotifier];
self.wifiReachability = [Reachability reachabilityForLocalWiFi];
[self.wifiReachability startNotifier];
}
return self;
}
Add this method in your Common Class.
/*================================================================================================
Check Internet Rechability
=================================================================================================*/
+(BOOL)checkIfInternetIsAvailable
{
BOOL reachable = NO;
NetworkStatus netStatus = [APP_DELEGATE1.internetReachability currentReachabilityStatus];
if(netStatus == ReachableViaWWAN || netStatus == ReachableViaWiFi)
{
reachable = YES;
}
else
{
reachable = NO;
}
return reachable;
}
Note that APP_DELEGATE1 Is an instance of AppDelegate
/* AppDelegate object */
#define APP_DELEGATE1 ((AppDelegate*)[[UIApplication sharedApplication] delegate])
You can check internet connectivity anywhere in app using this method.
it's simple , you can use following method to check internet connection .
-(BOOL)IsConnectionAvailable
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
return !(networkStatus == NotReachable);
}
Hope this helps you to network in Wifi mode only:
Utils.h
#import <Foundation/Foundation.h>
#interface Utils : NSObject
+(BOOL)isNetworkAvailable;
#end
utils.m
+ (BOOL)isNetworkAvailable
{
CFNetDiagnosticRef dReference;
dReference = CFNetDiagnosticCreateWithURL (NULL, (__bridge CFURLRef)[NSURL URLWithString:#"www.apple.com"]);
CFNetDiagnosticStatus status;
status = CFNetDiagnosticCopyNetworkStatusPassively (dReference, NULL);
CFRelease (dReference);
if ( status == kCFNetDiagnosticConnectionUp )
{
NSLog (#"Connection is Available");
return YES;
}
else
{
NSLog (#"Connection is down");
return NO;
}
}
//Now use this in required class
- (IBAction)MemberSubmitAction:(id)sender {
if([Utils isNetworkAvailable] ==YES){
NSlog(#"Network Connection available");
}
}
Try This to check internet connected or not
NSURL *url = [NSURL URLWithString:#"http://www.appleiphonecell.com/"];
NSMutableURLRequest *headRequest = [NSMutableURLRequest requestWithURL:url];
headRequest.HTTPMethod = #"HEAD";
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
defaultConfigObject.timeoutIntervalForResource = 10.0;
defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:nil delegateQueue: [NSOperationQueue mainQueue]];
NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:headRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
if (!error && response)
{
block([(NSHTTPURLResponse *)response statusCode] == 200);
}else{
block(FALSE);
}
}];
[dataTask resume];
Using Alamofire library:
let reachabilityManager = NetworkReachabilityManager()
let isReachable = reachabilityManager.isReachable
if (isReachable) {
//Has internet
}else{
//No internet
}
'Reachability' doesn't work since it won't detect if there is a response from the host or not. It will just check if the client can send out a packet to the host. So even if you are connected to a WiFi network and the WiFi's internet is down or the server is down, you will get a "YES" for reachability.
A better method is to try an HTTP request and verify the response.
Example below:
NSURL *pageToLoadUrl = [[NSURL alloc] initWithString:#"https://www.google.com/"];
NSMutableURLRequest *pageRequest = [NSMutableURLRequest requestWithURL:pageToLoadUrl];
[pageRequest setTimeoutInterval:2.0];
AFHTTPRequestOperation *pageOperation = [[AFHTTPRequestOperation alloc] initWithRequest:pageRequest];
AFRememberingSecurityPolicy *policy = [AFRememberingSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
[policy setDelegate:self];
currentPageOperation.securityPolicy = policy;
if (self.ignoreSSLCertificate) {
NSLog(#"Warning - ignoring invalid certificates");
currentPageOperation.securityPolicy.allowInvalidCertificates = YES;
}
[pageOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
internetActive = YES;
} failure:^(AFHTTPRequestOperation *operation, NSError *error){
NSLog(#"Error:------>%#", [error description]);
internetActive = NO;
}];
[pageOperation start];
Only catch is that the "internetActive" gets updated with a delay upto the timeout mentioned in the above code. You can code inside the callback to act on the status.
Updated answer for Swift 4.0 & AlamoFire:
The answer I posted on Sept 18 is incorrect, it only detects if it is connected to network, not internet. Here is the correct solution using AlamoFire:
1) Create custom Reachability Observer class:
import Alamofire
class ReachabilityObserver {
fileprivate let reachabilityManager = NetworkReachabilityManager()
fileprivate var reachabilityStatus: NetworkReachabilityManager.NetworkReachabilityStatus = .unknown
var isOnline: Bool {
if (reachabilityStatus == .unknown || reachabilityStatus == .notReachable){
return false
}else{
return true
}
}
static let sharedInstance = ReachabilityObserver()
fileprivate init () {
reachabilityManager?.listener = {
[weak self] status in
self?.reachabilityStatus = status
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: ClickUpConstants.ReachabilityStateChanged),
object: nil)
}
reachabilityManager?.startListening()
}
}
2) Initialize on app start up
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
_ = ReachabilityObserver.sharedInstance
return true
}
3) Use this anywhere in your app to detect if online, such as in view did load, or when action occurs
if (ReachabilityObserver.sharedInstance.isOnline){
//User is online
}else{
//User is not online
}
Try this
check this link for Reachability file
Reachability
import this file in your .m and then write code
//This is to check internet connection
BOOL hasInternetConnection = [[Reachability reachabilityForInternetConnection] isReachable];
if (hasInternetConnection) {
// your code
}
Hope it helps.
Reachability* reachability = [Reachability reachabilityWithHostName:#"www.google.com"];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if(remoteHostStatus == ReachableViaWWAN || remoteHostStatus == ReachableViaWiFi)
{
//my web-dependent code
}
else {
//there-is-no-connection warning
}
I start monitoring like this in my AppDelegate:
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
On my root controller I then need to check if reachability is available and I perform this action to decide how to draw my UI:
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
NSLog(#"%s - %#", __FUNCTION__, AFStringFromNetworkReachabilityStatus([manager networkReachabilityStatus]));
switch ([manager networkReachabilityStatus]){
case AFNetworkReachabilityStatusNotReachable:
[self showNetworkUnreachable];
break;
default:
[self hideNetworkUnreachable];
}
My issue is that here status is always unknown even if the device has connection.
Possibly AfNetworking is not the right tool to be used here. Any suggestion?
Not working in my case too. I used that instead:
- (BOOL)isInternetConnectionAvailable
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if (internetStatus != NotReachable) {
return YES;
}
else
{
NSLog(#"NO INTERNET CONNECTION");
return NO;
}
}
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
}