Reputation: 4600
I am trying to learn AFNetworking. when I run following code I get there is no internet. But in another check it says it is connected to the internet and device is connected to internet through wifi. This the output:
2016-02-19 15:16:40.315 AFNetworkingSample[377:47927] There is no internet connection
2016-02-19 15:16:40.331 AFNetworkingSample[377:47927] Reachability: Reachable via WiFi
Any idea why return value of connected method is false?
- (void)viewDidLoad {
[super viewDidLoad];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
if (self.connected)
{
NSLog(@"We have internet connection");
}
else
{
NSLog(@"There is no internet connection");
}
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
}];
}
-(BOOL)connected {
return [AFNetworkReachabilityManager sharedManager].reachable;
}
UPDATE When I change it to following it works fine and detect internet properly. Anyone can explain this behaviour?
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
if (self.connected)
{
NSLog(@"We have internet connection");
}
else
{
NSLog(@"There is no internet connection");
}
}];
UPDATE2
When I wait for two second it detects internet properly:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if (self.connected)
{
NSLog(@"We have internet connection");
}
else
{
NSLog(@"There is no internet connection");
}
});
UPDATE3:
Is this how to practice to avoid race condition?
- (void)viewDidLoad {
[super viewDidLoad];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
if([AFNetworkReachabilityManager sharedManager].reachable)
{
NSLog(@"Internet connection started again");
}
else
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Alert"
message:@"Error Retrieving Data"
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *firstAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
NSLog(@"You pressed button OK");
}];
[alert addAction:firstAction];
[self presentViewController:alert animated:YES completion:nil];
}
}];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
});
}
Upvotes: 2
Views: 1351
Reputation: 162722
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
The above is, effectively, an asynchronous call. You've told AFNetwork
that you're interested in reachability. As such, it is going to go off and do whatever it needs to do to determine and monitor reachability in the background.
Since it is not a one shot asynchronous call, having a completion block on that method doesn't really fit the pattern of a normal completion handler. It could have been a "status handler" that is called whenever a state change happens, but the API is also designed to be used for passive polling (which some of your other code patterns, like the timer one, inadvertently do -- and, as you noted, not waiting long enough gives you the wrong answer, as expected).
By calling setReachabilityStatusChangeBlock:
, you are registering a bit of code to be executed when the reachability status changes. Use that to trigger your "hey! reachability changed!" code, and all is well.
The only remaining issue is whether there is a race condition. You should probably set the block before calling startMonitoring
. And, to be safe, you'll likely want to check to see if the network is connected immediately after you call startMonitoring
as, technically, if the network was connected, then there may not be a state change that triggers a call to your state changed handler block.
You don't want to block the thread for 2 seconds to try and avoid the race condition. Do something like this:
... set up change handler block ...
... start monitoring ...
... check current internet state & alert user if necessary ...
Move your alert out of the change handler block and into a method that both the change handler block and the "check current internet state & alert user if necessary" mention above can call.
Upvotes: 1
Reputation: 4043
use Reachability like this.....
- (void)viewDidLoad {
if (self.isConnected)
{
NSLog(@"We have internet connection");
}
else
{
NSLog(@"There is no internet connection");
}
}
-(BOOL)isConnected
{
Reachability *aReachability = [Reachability reachabilityWithHostName:KWebserviceURL];
NetworkStatus netStatus = [aReachability currentReachabilityStatus];
if(netStatus==0)
{
// NoAccess
return NO;
}
else if(netStatus==1)
{
// ReachableViaWiFi
return YES;
} else if(netStatus==2)
{
// ReachableViaWWAN
return YES;
}
else
{
// Reachable
return YES;
}
}
if you want to make global class ror check internet connection then make NSObject see in my another ans....Check here
Hope it Helps you...
Upvotes: 0