How to test the availability of URL or NOT? - ios

I'm not found simple solution for this question on SO.
I need simple check logic for my URL and return YES - if available or NO - if not.
What i found:
-(BOOL)connectedToNetwork {
NSURL* url = [[NSURL alloc] initWithString:#"http://google.com/"];
NSData* data = [NSData dataWithContentsOfURL:url];
if (data != nil)
return YES;
return NO;
}
founded this
But i need more correctly answer.
UPD
I found SimplePing by Apple.
UPD1
Found answer on SO Thx all!
UPD2
Better solution SimplePingHelper required SimplePing:
- (void)tapPing {
[SimplePingHelper ping:#"www.google.com"
target:self sel:#selector(pingResult:)];
}
- (void)pingResult:(NSNumber*)success {
if (success.boolValue) {
[self log:#"SUCCESS"];
} else {
[self log:#"FAILURE"];
}
}

The preferred approach is trying to connect, and if that fails due to the host is not reachable check and monitor the network state. See Reachability. If the network state indicates that a host can be possibly reached, try again.
There are also a couple of third party libs that implement a handy API over Apple's Reachability interface.

I use AFNetworking to check reachability.
Pod file: pod "AFNetworking"
You have to include AFNetworkReachabilityManager.h in the file you want to use it.
This is a sample, basic code to check reachability.
// -- Start monitoring network reachability (globally available) -- //
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Reachability changed: %#", AFStringFromNetworkReachabilityStatus(status));
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
// -- Reachable -- //
NSLog(#"Reachable");
break;
case AFNetworkReachabilityStatusNotReachable:
default:
// -- Not reachable -- //
NSLog(#"Not Reachable");
break;
}
}];

A valid URL is made of these characters :
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]#!$&'()*+,;=
You simply need to make a String checking function to validate your URL's characters are falling in or out.

Its was simple:
-(BOOL)connectedToNetwork {
NSURL* url = [[NSURL alloc] initWithString:#"http://google.com/"];
NSData* data = [NSData dataWithContentsOfURL:url];
if (data != nil)
return YES;
return NO;
}
founded this

Related

Apple's weather app fetches as soon as an Internet connection is made after being disconnected. Is there a better way to do this besides a while loop?

Psuedocode of my current solution:
if (disconnected):
while (disconnected):
check for connection
if (connected):
fetch results
Is there a more idiomatic way to tell when the device goes from being disconnected to establishing an internet connection?
Take a look at Apple's Reachability sample code
You don't have to investigate detailed implementation of Reachability.m. You can just use it as a library.
Absolutely! This is what SCNetworkReachability is for!
Unfortunately, people tend to use it incorrectly. What you are describing would be a correct use case for it.
Attempt a connection normally.
If it fails with NSURLErrorNotConnectedToInternet:
Use SCNetworkReachability to monitor the device network configuration for changes
When the network configuration moves to a state that indicates packets can again leave the device, your application will be notified and you can make connections again.
What you should NOT do is try to use SCNetworkReachability to see if the device is connected before connecting. This is not recommended for many reasons. The SCNetworkReachability API can tell you when it is, or is not, possible for packets to leave the device. It can't tell you if the thing you're connecting to is down, DNS isn't working, etc.
The Apple sample projects MVCNetworking and Reachability demonstrate use of the SCNetworkReachability API.
In practice, this looks like....
In your connection error handling:
if ([[error domain] isEqualToString:NSURLErrorDomain]){
NSURL *failingURL = [[error userInfo] valueForKey:NSURLErrorFailingURLErrorKey];
switch ([error code]){
case NSURLErrorNotConnectedToInternet:
[self beginObservingReachabilityStatusForHost:[failingURL host]];
break;
default:
break;
}
}
The beginObservingReachabilityStatusForHost: and endObsvervingReachabilityStatusForHost: methods:
- (void) beginObservingReachabilityStatusForHost:(NSString *)host {
SCNetworkReachabilityRef reachabilityRef = NULL;
void (^callbackBlock)(SCNetworkReachabilityFlags) = ^(SCNetworkReachabilityFlags flags) {
BOOL reachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self host:host didBecomeReachable:reachable];
}];
};
SCNetworkReachabilityContext context = {
.version = 0,
.info = (void *)CFBridgingRetain(callbackBlock),
.release = CFRelease
};
if ([host length] > 0){
reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [host UTF8String]);
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)){
if (!SCNetworkReachabilitySetDispatchQueue(reachabilityRef, [self scNetworkQueue]) ){
// Remove our callback if we can't use the queue
SCNetworkReachabilitySetCallback(reachabilityRef, NULL, NULL);
}
[self setCurrentReachability:reachabilityRef];
}
}
}
- (void) endObsvervingReachabilityStatusForHost:(NSString *)host {
// Un-set the dispatch queue
if (!SCNetworkReachabilitySetDispatchQueue([self currentReachability], NULL) ){
}
SCNetworkReachabilitySetCallback([self currentReachability], NULL, NULL);
}
The C callback that wraps our block:
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkConnectionFlags flags, void* info) {
void (^callbackBlock)(SCNetworkReachabilityFlags) = (__bridge id)info;
callbackBlock(flags);
}
And the method that the block calls to do something when reachability changes:
- (void) host:(NSString *)host didBecomeReachable:(BOOL)reachable {
// Update your UI to indicate reachability status here
if (reachable){
[self endObsvervingReachabilityStatusForHost:nil];
}
}
Obviously to use the above you need a serial dispatch queue and a way to hold on to the SCNetworkReachabilityRef for later cancellation when you're done.

libPayPalEC.a without uniqueIdentifier?

today I've tried to send my updated app and the apple declined my app for using uniqueIdentifier. After some research I found, that libPayPalEC.a is using uniqueIdentifier 3 times.
Via terminal: strings .Lib/PayPal/libPayPalEC.a | grep uniqueIdentifier
Does any one now where I can download updated library? I was looking everywhere...
Thank you,
Please refer to the issue here on github: https://github.com/paypal/PayPal-iOS-SDK/issues/13
After some reasearch and great answer on github: https://github.com/paypal/PayPal-iOS-SDK/issues/13#issuecomment-17882240 I've removed paypal library, removed deviceToken generation and the PayPal mobile is working!
How to use PayPal payment without library:
You need to create the payment process on the backend (like PHP) and in the iOS app just open the web view with URL to your backend. To process success or error handle the web view request so you can catch link like error, cancel or success (the pages, which the backend redirects).
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *urlString = [[request.URL absoluteString] lowercaseString];
if (urlString.length > 0) {
//80 is the default HTTP port.
//The PayPal server may add the default port to the URL.
//This will break our string comparisons.
if ([request.URL.port intValue] == 80) {
urlString = [urlString stringByReplacingOccurrencesOfString:#":80" withString:#""];
}
NSLog(#"URL %#",urlString);
if ([urlString rangeOfString:#"success"].location != NSNotFound) {
// handle error
if (visible) {
[self dismissViewControllerAnimated:YES completion:complete];
} else {
dismissOnAppear = YES;
}
return FALSE;
} else if ([urlString rangeOfString:#"cancel"].location != NSNotFound) {
// handle error
if (visible) {
[self dismissViewControllerAnimated:YES completion:complete];
} else {
dismissOnAppear = YES;
}
return FALSE;
} else if ([urlString rangeOfString:#"error"].location != NSNotFound) {
// handle error
if (visible) {
[self dismissViewControllerAnimated:YES completion:complete];
} else {
dismissOnAppear = YES;
}
return FALSE;
}
}
return TRUE;
}
On the backend handling you don't need to sent dirt token (from the iOS library) any more, you just work with token from paypal as the standard way.
As the payment method use _express-checkout not _express-checkout-mobile and don't send drt as deviceToken.

App Checking for updates

I am creating a update method for in house enterprise apps. What I am trying to create is a class that I can quickly put in a app and it will check with the server if it needs to be updated. This is what I have so far, it checks correctly but its returning NO before it finishes the method.
In my checkUpdate.h
#interface checkForUpdate : NSObject
+ (BOOL)updateCheck;
#end
In my checkUpdate.m
#import "checkForUpdate.h"
#implementation checkForUpdate
BOOL needsUpdate
NSDictionary *versionDict;
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
+ (BOOL)updateCheck {
NSString *urlStringVersion = [[NSString alloc] initWithFormat:#"http://URL/app_info?app=app"];
NSURL *urlVersion = [NSURL URLWithString:urlStringVersion];
dispatch_async(kBgQueue, ^{
NSData* data =[NSData dataWithContentsOfURL:urlVersion];
if (data){
NSError* error;
NSArray* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (json != nil && [json count] != 0) {
versionDict = [json objectAtIndex:0];
CGFloat serverVersion = [[versionDict valueForKey:#"version"]floatValue];
CGFloat appVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey] floatValue];
NSLog(#"Server Version %f",serverVersion);
NSLog(#"App Version %f",appVersion);
if ([versionDict count] != 0){
if (serverVersion > appVersion){
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1];
needsUpdate = YES;
}else{
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
needsUpdate = NO;
}
}
}
}
});
return needsUpdate;
}
#end
I call it like this
NSLog(#"Needs Update %#",[checkForUpdate checkForUpdateWithResponse] ? #"Yes":#"No");
This is my log
Needs Update No
Server Version 2.000000
App Version 1.000000
I'm not sure why it's returning NO before it even checks. I need it to be a asynchronous because the server that the app will check with is behind our firewall. So if the person is outside the firewall the app needs to continue when is can't reach the server. I'm I headed in the right direction, or is there a better way?
You are asynchronously checking for an update but expecting an immediate response by virtue of your method's design. You can re-engineer your method to something like the example below to notify a handler whenever the operation is complete:
Note: Unchecked and untested for errors; however, the lesson to be gleaned from the example is to use a callback of sorts:
UpdateChecker Class
typedef void (^onComplete)(BOOL requiresUpdate);
#interface UpdateChecker : NSObject
-(void)checkForUpdates:(onComplete)completionHandler;
#end
#implementation UpdateChecker
-(void)checkForUpdates:(onComplete)completionHandler
{
NSString *urlStringVersion = [[NSString alloc] initWithFormat:#"http://URL/app_info?app=app"];
NSURL *urlVersion = [NSURL URLWithString:urlStringVersion];
dispatch_block_t executionBlock =
^{
/*
Your update checking script here
(Use the same logic you are currently using to retrieve the data using the url)
*/
NSData* data = [NSData dataWithContentsOfURL:urlVersion];
BOOL requiresUpdate = NO;
if (data)
{
...
...
...
requiresUpdate = ...; //<-whatever your outcome
}
//Then when completed, notify the handler (this is our callback)
//Note: I typically call the handler on the main thread, but is not required.
//Suit to taste.
dispatch_async(dispatch_get_main_queue(),
^{
if (completionHandler!=NULL)
completionHandler(requiresUpdate);
});
};
dispatch_async(kBgQueue, executionBlock);
}
#end
This is what it would look when you use UpdateChecker to check for updates throughout your app
UpdateChecker *checker = [UpdateChecker alloc] init];
[checker checkForUpdates:^(BOOL requiresUpdate)
{
if (requiresUpdate)
{
//Do something if your app requires update
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1];
}
else
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}];
Since dispatch_async is non-blocking, your method returns before your update information has returned (does the dispatch and continues). As needsUpdate defaults to NO, that's what you'll see. You can see this in your log timing - the "Needs Update No" shows up before the server and app versions.
You need some sort of callback (a delegate method or second dispatch_async for example) to ensure you get the correct result, or you need to block. I recommend looking into NSURLConnection, and sendAsynchronousRequest:queue:completionHandler: - it will execute the completion handler on completion, where you can have whatever code you need for handling the update.

To check wifi is on but no internet connectivity

i m using reachability classes to check wifi connectivity in my code. But sometimes problem arise that wifi is ON but there is no or low internet connectivity, here my code runs in loop waiting for any response from called webservice and hangsup and crashes sometimes.
Below Code is executed when i hit OK on an AlertView which pulls some data from webservice
Here is my code :
Reachability *ReachObj = [Reachability reachabilityForInternetConnection];
[ReachObj startNotifier];
NetworkStatus remoteHostStatus = [ReachObj currentReachabilityStatus];
if (remoteHostStatus==ReachableViaWiFi)
{
SecondView *ObjSecView=[[SecondView alloc]init];
[self presentModalViewController:ObjSecView animated:YES];
}
else
if (remoteHostStatus==NotReachable)
{
FirstView *objFrstView=[[FeedBackPopOverViewController alloc]init];
[self presentModalViewController:objFrstView animated:YES];
}
Guys i m new to Objective C.
Plz help me out, thanks in advance. And sorry for my grammatical mistakes.
try this..
SCNetworkReachabilityFlags flags;
SCNetworkReachabilityRef reachability=SCNetworkReachabilityCreateWithName(NULL, [#"your web sevice url" UTF8String]);
SCNetworkReachabilityGetFlags(reachability, &flags);
BOOL reachable=!(flags & kSCNetworkReachabilityFlagsConnectionRequired);
CFRelease(reachability);
NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
if([NSURLConnection canHandleRequest:request] && reachable)
{
conn=[NSURLConnection connectionWithRequest:request delegate:self];
if(conn)
{
////
}
else
{
[_delegate performSelector:#selector(httpDataDidFailLoadingWithReason:)
withObject:#"No Internet Connection" afterDelay:0.1];
}
}
-(void) httpDataDidFailLoadingWithReason:(NSString*)reason
{
UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:#"abc"
message:reason
delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
-(void)loginButtonTouched
{
bool success = false;
const char *host_name = [#"www.google.com"
cStringUsingEncoding:NSASCIIStringEncoding];
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName
(NULL, host_name);
SCNetworkReachabilityFlags flags;
success = SCNetworkReachabilityGetFlags(reachability, &flags);
bool isAvailable = success && (flags & kSCNetworkFlagsReachable) &&
!(flags & kSCNetworkFlagsConnectionRequired);
if (isAvailable)
{
NSLog(#"Host is reachable: %d", flags);
// Perform Action if Wifi is reachable and Internet Connectivity is present
}
else
{
NSLog(#"Host is unreachable");
// Perform Action if Wifi is reachable and Internet Connectivity is not present
}
}
When loginButtonTouched method is called we check that "www.google.com" is reachable or not.
SCNetworkReachabilityFlags returns flags which helps us to understand the Status of internet connectivity.
If isAvailable variable returns "true" then Host is Reachable means Wifi is reachable and Internet Connectivity is present.
And thanks to all for providing with your quick answers to our questions.
Sorry all for my grammatical mistakes.

Reachability Guide for iOS

Has anyone found a halfway decent guide to implementing Reachability on iOS?
I have implemented Reachability like this.
Download https://developer.apple.com/library/content/samplecode/Reachability/Introduction/Intro.html and add Reachability.h and .m to your project. Add the SystemConfiguration framework to your project. #import "Reachability.h" where you want to use it. Use this code.
-(BOOL)reachable {
Reachability *r = [Reachability reachabilityWithHostName:#"enbr.co.cc"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if(internetStatus == NotReachable) {
return NO;
}
return YES;
}
When you want to check for reachability...
if ([self reachable]) {
NSLog(#"Reachable");
}
else {
NSLog(#"Not Reachable");
}
Here is the example project that I made. http://dl.dropbox.com/u/3656129/ReachabilityExample.zip
I think the best way to check the availability of host address is by checking the results of NSURL Request.
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:reqURL]];
NSURLResponse *resp = nil;
NSError *error = nil;
NSData *response = [NSURLConnection sendSynchronousRequest: theRequest returningResponse: &resp error: &error];
NSString *responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
Using this bit of Code, if your device cannot reach the provided URL, it provides some output to the error variable, if it can access the URL Request, error is Nil.
Reachability gives a positive output even if you URL packets can route out from your device and never reach the host server.
This question seems to have only obsolete answers. Since iOS 12 we have NWPathMonitor so you should at least look into that as well.

Resources