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.
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 use reachability to detect network change. the first time its ok with wifi available. but then i turn off wifi then turn on, it alway return NotReach
Reachability *internetChecker;
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(myMethod:) name:kReachabilityChangedNotification object:nil];
internetChecker = [Reachability reachabilityWithHostName:#"www.24h.com.vn"];
[internetChecker startNotifier];
in mymethod:
NetworkStatus status = [internetChecker currentReachabilityStatus];
switch (status) {
case NotReachable:
{
NSLog(#"no wifi");
break;
}
default:
{
NSLog(#"wifi");
break;
}
}
Do you have separate Reachability properties for the Internet and the Host?
#property (nonatomic) Reachability *internetReachability;
#property (nonatomic) Reachability *hostReachability;
Then do this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMethod:) name:kReachabilityChangedNotification object:nil];
self.internetReachability = [Reachability reachabilityForInternetConnection];
[self.internetReachability startNotifier];
[self updateInterfaceWithReachability:self.internetReachability];
self.hostReachability = [Reachability reachabilityWithHostName:#"www.24h.com.vn"];
[self.hostReachability startNotifier];
[self updateInterfaceWithReachability:self.hostReachability];
Then myMethod:
- (void)myMethod:(NSNotification *)note
{
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
[self updateInterfaceWithReachability:curReach];
}
And updateInterfaceWithReachability:
- (void)updateInterfaceWithReachability:(Reachability *)reachability {
NetworkStatus netStatus = [reachability currentReachabilityStatus];
if (reachability == self.internetReachability) {
switch (netStatus) {
case NotReachable:
NSLog(#"no internet");
break;
case ReachableViaWWAN:
case ReachableViaWiFi:
NSLog(#"with internet");
break;
}
}
if (reachability == self.hostReachability) {
switch (netStatus) {
case NotReachable:
NSLog(#"www.24h.com.vn unavailable");
break;
case ReachableViaWWAN:
case ReachableViaWiFi:
NSLog(#"www.24h.com.vn available");
break;
}
}
Try below solution
+ (BOOL)checkInternetConnection
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];
if (remoteHostStatus == NotReachable)
{
return FALSE;
}
else
{
return TRUE;
}
}
you have to modify this line
Reachability * internetChecker = [Reachability reachabilityForInternetConnection];
Hope it helps you..!
done! i dont know how but its seem notification center only detect when network change. When it notice the status is still NotReachable. So i check for the network after 2s delay. It work!
I'm using Apple's Reachability framework, "api.parse.com" is ALWAYS Unreachable. Am I missing something?
In my viewDidLoad, I have this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
self.hostParseReachability = [Reachability reachabilityWithHostName:kParseConnectivityTestURL];
[self.hostParseReachability startNotifier];
[self updateInterfaceWithReachability:self.hostParseReachability];
Then I have the following Reachability methods:
-(void)reachabilityChanged:(NSNotification* )note
{
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
[self updateInterfaceWithReachability:curReach];
}
- (void)updateInterfaceWithReachability:(Reachability *)reachability {
NetworkStatus netStatus = [reachability currentReachabilityStatus];
if (reachability == self.internetReachability) {
switch (netStatus) {
case NotReachable:
isConnectedToInternet = NO;
break;
case ReachableViaWWAN:
case ReachableViaWiFi:
isConnectedToInternet = YES;
break;
}
}
if (reachability == self.hostParseReachability) {
switch (netStatus) {
case NotReachable:
isParseOnline = NO;
break;
case ReachableViaWWAN:
case ReachableViaWiFi:
isParseOnline = YES;
break;
}
}
Parse is ALWAYS offline for me, but I can perform queries.
They have a firewall blocking ICMP packets. If you need to check manually if everything is fine - you can try curl
If parse is unreachable, you'll get kPLParseConnectionFailed (in case of iOs app).
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");
}
}
}
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;
}
}