I have a method implemented thats tests the internet connection in my iOS app. The problem is, I only want the method to test the internet connection over wifi, not cellular. How do I do that? :-) PS I'm using the latest version of Xcode & iOS 6.
NSURL *scriptUrl = [NSURL URLWithString:#"http://10.247.245.87/stores/test.html"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data != nil){
UIAlertView *alert = [[UIAlertView alloc]initWithTitle: #"Success"
message: #"You're connected to the server"
delegate: self
cancelButtonTitle: #"Close"
otherButtonTitles:nil];
//Show Alert On The View
[alert show];
}
else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle: #"Connection Failed"
message: #"Please connect to network and try again"
delegate: self
cancelButtonTitle: #"Close"
otherButtonTitles:nil];
//Show Alert On The View
[alert show];
}
Have you looked into the Reachability class?
http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html
It will probably provide you with a lot more flexibility and why roll your own if Apple has already done the work :) Hope this helps!
Check Tony Million Reachability class
There must be a isReachableViaWiFi method you can check wifi only
// allocate a reachability object
Reachability* reach = [Reachability reachabilityWithHostname:#"www.google.com"];
// tell the reachability that we DONT want to be reachable on 3G/EDGE/CDMA
reach.reachableOnWWAN = NO;
Have you looked at this similar question:
How to check for an active Internet connection on iOS or OSX?
The highest up voted question on that gives a github link to a neat workaround and shows you if the internet connection is active via wifi or WWAN (cellular)
AFNetworking providing facility to check network connectivity -
AFNetworkReachabilityManager.sharedManager().setReachabilityStatusChangeBlock { (status: AFNetworkReachabilityStatus) -> Void in
// check your connectivity...
}
Related
I am new to iOS App development. I have a sample App which is written in Swift.
I am using a WKWebView in my web application.
However, when the mobile network/Wifi is not available. It is showing blank screen.
I would like to prompt a dialog box to refresh the current page to the user when
1. If network is not present
2. My server is not available to be accessed.
Use WebView delegate method to find network error.
-(void)webView:(UIWebView )webView didFailLoadWithError:(NSError )error
{
NSString *str = [NSString stringWithFormat:#"%li",(long)error.code];
if ([str isEqualToString: #"-1009"])//network unavailable error code
{
UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:#"Network Error" message:#"Internet or Wifi is not available. Please check your network connection & try again." delegate:self cancelButtonTitle:#"Retry" otherButtonTitles:nil];
[alertView show];
str = #"";
}
NSLog(#"%#",[super appUrl]);
}
Then retry in AlertView delegate method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex==0){
if ([super appUrl]) {
NSURLRequest* appReq = [NSURLRequest requestWithURL:yourURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
[self.webView loadRequest:appReq];
} }
}
P.S. use similar to work with swift.
I am working on an iOS chat app where user login to app. I've downloaded XMPPFramework from GitHub XMPPFramework. I am trying to connect XMPP framework with Openfire server by following this tutorial. Here is my code to connect XMPP to openfire.
- (BOOL)connect {
[self setupStream];
[xmppStream setHostName:#"192.168.1.5"];
[xmppStream setHostPort:5222];
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:#"userID"];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:#"userPassword"];
if (![xmppStream isDisconnected])
return YES;
if (jabberID == nil || myPassword == nil)
return NO;
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream isConnected])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
return NO;
}
return YES;
}
The problem is when I run the app, it shows the alert can't connect to server. I have checked many questions on StackOverflow and tried googling but couldn't find any relevant solution. How to connect it to the Openfire serve? If I am doing anything wrong in my code please suggest me with a snippet of code or a tutorial to make this happen.
A host of possibilities.
Try adding break points at xmppStreamDidConnect and xmppStreamDidAuthenticate.
If xmppStreamDidConnect isn't reached, the connection is not established; you've to rectify your hostName.
If xmppStreamDidAuthenticate isn't reached, the user is not authenticated; you've to rectify your credentials i.e. username and/or password.
One common mistake is omitting of #domainname at the back of username i.e. username#domainname e.g. keithoys#openfireserver where domain name is openfireserver.
Hope this still relevant, if not, hopefully it will help others.
There are some issues with your code:
I don't see the call to connect, you should add something like this:
NSError *error = nil;
if (![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error connecting"
message:#"Msg"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
Most of the XMPP API is asynchronous.
You have to set the stream delegate in order to receive events.
Check out XMPPStreamDelegate and XMPPStream#addDelegate
If you don't want to go through the code yourself XMPPStream.h
, you can implement all methods of XMPPStreamDelegate and log the events. This will help you understand how the framework works.
Hope this helps, Yaron
I am trying to setup Reachability using the new 2.0 AFNetworking.
In my AppDelegate I initialise the sharedManager.
// Instantiate Shared Manager
[AFNetworkReachabilityManager sharedManager];
Then in the relevant VC method I check to see if isReachable:
// Double check with logging
if ([[AFNetworkReachabilityManager sharedManager] isReachable]) {
NSLog(#"IS REACHABILE");
} else {
NSLog(#"NOT REACHABLE");
}
At present this is not working as expected in the simulator, but I imagine this would need to be tested on device and not simulator.
Question
What I would like to do is monitor the connectivity within the VC. So I run the following in the viewDidLoad:
// Start monitoring the internet connection
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
How would I then register for the changes? What is/would be called once the network connection changes I cannot see this from the documentation.
As you can read in the AFNetworking read me page
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Reachability: %#", AFStringFromNetworkReachabilityStatus(status));
}];
Here's also a link to the official documentation.
I have a singleton AFHTTPRequestOperationManager class. In the singleton has a method:
+(void)connectedCompletionBlock:(void(^)(BOOL connected))block {
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
BOOL con = NO;
NSLog(#"Reachability: %#", AFStringFromNetworkReachabilityStatus(status));
if (status == AFNetworkReachabilityStatusReachableViaWWAN || status == AFNetworkReachabilityStatusReachableViaWiFi) {
con = YES;
}
if (block) {
[[AFNetworkReachabilityManager sharedManager] stopMonitoring];
block(con);
}
}];
}
Before make a request you call this method that return a block indicating if internet is reachable:
[TLPRequestManager connectedCompletionBlock:^(BOOL connected) {
if (connected) {
// Make a request
}else{
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Notice" message:#"Internet is not available." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alertView show];
}
}];
I was just going through your question and all the answers. After that I decided to do all these things once. So, in my existing project I just included the AFNetworking through cocoa-pods and here is the solution which is woking for me completely.
Solution -- First of all AFNetworkReachabilityManager is a singleton class. You don't need to do AppDelegate initialisation for sharedManager.
//[AFNetworkReachabilityManager sharedManager];
#import <AFNetworkReachabilityManager.h>
- (void)viewDidLoad {
//Starting the network monitoring process
[[AFNetworkReachabilityManager sharedManager]startMonitoring];
//Checking the Internet connection...
[[AFNetworkReachabilityManager sharedManager]setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status){
if (status == AFNetworkReachabilityStatusReachableViaWWAN || status == AFNetworkReachabilityStatusReachableViaWiFi) {
UIAlertView *alertNetFound = [[UIAlertView alloc]initWithTitle:#"Network Found" message:#"Please Wait Until It is loading" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertNetFound show];
}else{
UIAlertView *alertNetNotFound = [[UIAlertView alloc]initWithTitle:#"No Internet" message:#"Please Check Your Internet Connection Honey" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertNetNotFound show];
}
}];
So, in this case every time the device connects to a network, it will do the startMonitoring process first and after that it will hit the status block every time and will display alert according to the status.
You can do anything according to your choice by replacing the alerts on the status block. I used this to load an webpage automatically from local storage but I removed that code for simplicity.
Its even working with my simulator and Mac mini..
Thanks
Hope this helped.
I use this in the app delegate ->
func reachablityCode() {
AFNetworkReachabilityManager.sharedManager()
AFNetworkReachabilityManager.sharedManager().startMonitoring()
AFNetworkReachabilityManager.sharedManager().setReachabilityStatusChangeBlock({(status) in
let defaults = NSUserDefaults.standardUserDefaults()
if status == .NotReachable {
defaults.setBool(false, forKey:REACHABLE_KEY)
}
else {
defaults.setBool(false, forKey: REACHABLE_KEY)
}
defaults.synchronize()
})
}
And then this in the base file ->
func isReachable() -> Bool {
return NSUserDefaults.standardUserDefaults().boolForKey(REACHABLE_KEY)
}
In my app there's a UIWebView showing a web page. It sometimes displays errors in a UIAlertView that are really annoying. I would like to intercept this and show the errors in a more sophisticated way.
Is there a way where i can intercept the error message in a function and decide for myself what i want to do with it?
Thanks in advance!
This seems to do it:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
JSContext *ctx = [webView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
ctx[#"window"][#"alert"] = ^(JSValue *message) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"JavaScript Alert" message:[message toString] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
};
}
Note: only tested on iOS 8.
I want to execute some code only, and only if I am connected to the internet:
//Reachability
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
Reachability * reach = [Reachability reachabilityWithHostname:#"www.dropbox.com"];
reach.reachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Block Says Reachable");
connect = #"yes";
});
};
reach.unreachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
connect = #"no";
});
};
[reach startNotifier];
//Reachability
if (connect == #"no") {
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"There is no internet connection. Please connect to the internet. If you are already connected, there might be a problem with our server. Try again in a moment." delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
} else if (titleSet == NULL){
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"Please select a group or create a new one" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
}else if (NavBar.topItem.title.length < 1){
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"Please select a group or create a new one" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
} else if (newmessagename.text.length < 4){
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"Please give a name to your event that is at least 4 characters long" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
}
It seems that the code is not executed in order. I think it is taking more time to check the Internet connection than it takes to execute the code. How can I fix this?
Please do not tell me to place the code directly in the parenthesis where connect = #"no"; is located.
The blocks aren't executed sequentially, they are executed asynchronously.
This means that you can't tell when the code inside the blocks is going to be called. The code using the block may finish and execute before the rest of your method (however this is unlikely, especially with Internet connections).
You should place your ifs in a method that is called at a valid time. This time is probably when you receive a response from your blocks, or, if my memory serves true, [reach startNotifier]; can notify you when there is a change in reachability status, this appears to be your reachabilityChanged: method:
-(void) reachabilityChanged:(id) parameter
{
//Query reachability and notify / cache as required.
}
Of course its not executed in order, the whole point of those methods is to stop the ui to freeze while you get your reachability response. Basically you set up the reachability responses and immediately ask for the result when nothing has been checked yet. What you have to really is to move it inside the brackets.
Something else that you can do is make a function with those results, and call this function in both of the blocks.
If you want to have this on the load of the viewcontroller or before you display anything else, then you either have to check for reachability before you show this controller, or add a "loading" screen.
EDIT: Something else that i dont understand is, those reachability methods seem to fire a block when they get the results, but you are registering for a notification as well. And i dont see you posting a notification for this. You are using 2 asynchronous approches here (blocks and notifications)