Objective C - Using Reachability to constantly check for network connection during download - iphone

I am using this piece of code to check for a network connection within my application and, if a connection exists, pull data and display it:
if([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == NotReachable) {
errorView = [[UIAlertView alloc]
initWithTitle: #"Network Error"
message: #"No Network connection availible!"
delegate: self
cancelButtonTitle: #"OK" otherButtonTitles: nil];
[errorView show];
}
else
{
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Performing Initial Download";
HUD.minSize = CGSizeMake(135.f, 135.f);
[HUD showWhileExecuting:#selector(pullAndDisplayData) onTarget:self withObject:nil animated:YES];
}
However, I would like to adapt this code so that it constantly checks for internet connection throughout the download process, and if I lose connection, to stop the download and display and appropriate alert message to the user. Can anyone advise as to how I may go about this?
Thanks,
Tysin

You need to add an observer for notification name
kReachabilityChangedNotification
and then call
[[Reachability reachabilityForInternetConnection] startNotifier];
When reachability changes, the notification will be posted, and then you can perform any actions you need.

Related

xcode webview error not working

This web view failed error showing the alert popup even when it is loading the website. I believe I need to delay this method in order for it to work.What will be the best method for doing this?
- (void)webView:(UIWebView *)webViewfail didFailLoadWithError:(NSError *)error
{
if([webViewfail isEqual:webview]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Connection Failed" message:#"Check your Internet connection before refreshing."
delegate:webview
cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
Here is how I am loading the website
- (void)viewDidLoad
{
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.blabla.com"]]];
}
The problem is most likely an error -999 which generally happens when something from the webpage does not load correctly or a user tries to navigate back while the page is still loading. After some research here's what I found and used to keep the NetworkAlert from poping up every time but still popping up when there is no network.
-(void)webView:(UIWebView *)webBlog didFailLoadWithError:(NSError *)error{
if ([error code] != -999) {
NSLog(#"Could not load the dumb webPage");
//show error alert, etc.
[self showNoNetworkAlert];
}else{
NSLog(#"Could not load the dumb web page...just might blame user!");
}
}
- (void) showNoNetworkAlert{
UIAlertView *baseAlert = [[UIAlertView alloc]
initWithTitle:#"No Network" message:#"A network connection is required. Please verify your network settings and try again."
delegate:nil cancelButtonTitle:nil
otherButtonTitles:#"Dismiss", nil];
[baseAlert show];
}
Hope this helps someone...

How to check network connection in iphone

this code is to check if internet connection is available or not.If internet connection is available then username and password should get validated from server database i.e send request method should get called and if not then username and password should get validated from local database i.e check method should get called.but the prob here is when the internet is off then also it gets into the send request method instead of getting in check nethod.What may be the prob.Please help me in solving this problem. i have added reachability files and imported the CFNetwork.framework.
- (void) showNetWorkAlert {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
UIAlertView *networkAlert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Network connection unavailable."
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"Retry", nil];
[networkAlert show];
[networkAlert release];
}
#pragma mark To Check Network Connection.
- (BOOL) currentNetworkStatus {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
BOOL connected;
const char *host = "www.apple.com";
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host);
SCNetworkReachabilityFlags flags;
connected = SCNetworkReachabilityGetFlags(reachability, &flags);
BOOL isConnected = YES;
isConnected = connected && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
CFRelease(reachability);
if(!isConnected) {
// sleep(1);
[self showNetWorkAlert];
//[self check];
}
else
return isConnected;
//[self sendRequest];
return isConnected;
}
-(IBAction)buttonPressed:(id)sender
{
//[self sendRequest];
//[[Reachability sharedReachability] setHostName:kHostName];
//Set Reachability class to notifiy app when the network status changes.
//[[Reachability sharedReachability] setNetworkStatusNotificationsEnabled:YES];
//Set a method to be called when a notification is sent.
//[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reachabilityChanged:) name:#"kNetworkReachabilityChangedNotification" object:nil];
//[self updateStatus];
//[self sendRequest];
//NSLog(<#NSString *format#>)
//this is to select username and password from database.
//[self check];
if ([self currentNetworkStatus]) {
[self sendRequest];
}
else {
[self check];
}
}
Rocky your code is right .Just check the URL is proper or not .
there is other way also
On button check the host like this
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
hostReach = [[Reachability reachabilityWithHostName:#"www.google.com"]retain];
[hostReach startNotifier];
and in the (reachabilityChanged:) method call make like this
-(void)reachabilityChanged:(NSNotification*)note
{
static BOOL showNotConnnected =NO;
Reachability *curReach =[note object];
NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
NetworkStatus netStatus = [curReach currentReachabilityStatus];
if(netStatus != NotReachable)
{
UIAlertView *notconnect1 = [[UIAlertView alloc]initWithTitle:#"Server is connected" message:#"Server is connected" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:#"Cancel",nil];
[notconnect1 show];
[notconnect1 release];
}
else if(showNotConnnected == NO)
{
showNotConnnected =YES;
UIAlertView *notconnect = [[UIAlertView alloc]initWithTitle:#"Server is Not connected" message:#"Server may be slow or not connected" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:#"Cancel",nil];
[notconnect show];
[notconnect release];
}
}
I hope this will help you
I do think there is a sample code called Reachability from apple can help you. see the URL below
http://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html
You should look at Apple's reachability code to check for a connection to the Internet. There is a sample project you can get from them in the iOS Developer Portal.
Reachability should not be used to detect if the network is available before making a network request because the act of making a network request can bring up the network if needed. Reachability should only be used to detect when the network becomes available after being unavailable.
Just try making the network request -- you'll get an error back if the network is unavailable. Usually the response will come back right away, but if the network is spotty it can take a while, so you shouldn't ever make synchronous network calls on the main thread. Use NSURLConnection if possible and you'll get callbacks when something happens.

How to trigger an action after a certain amount of time?

In my app i want to display an error message if the network connection is too slow after few seconds. How should i implement this?
Here's the code:
-(void)setProjectID:(NSString *)newProject {
[self willChangeValueForKey:#"projectID"];
[projectID release];
projectID = [newProject copy];
[self didChangeValueForKey:#"projectID"];
// Since we have an ID, now we need to load it
NSInvocation *returnInvocation = [NSInvocation invocationWithMethodSignature:
[Detail instanceMethodSignatureForSelector:#selector(configureView:)]];
[returnInvocation setTarget:self];
[returnInvocation setSelector:#selector(configureView:)];
[returnInvocation retainArguments];
fetch = [[WBWDocumentFetcher alloc] init];
[fetch retrieveDocument:[NSURL wb_URLForTabType:PROJECT_DETAILS inProject:projectID] returnBy:returnInvocation];
}
-(void)configureView:(NSDictionary *)serverResult
{
}
Thanks,
You want to use performSelector:afterDelay: or possibly performSelector:withObject:afterDelay:.
Then, at the beginning of the method called, check to see if the page has loaded. If not, then display a UIAlertView and cancel the load.
If you are using NSURLRequest for requesting server than use following code to judge time out.
//In this you can set timeoutinterval for request
NSURLRequest* request = [NSURLRequest requestWithURL:yourURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
//If request is failing for time out reason you can check that and alert user accordingly.
-(void)connectionFailed:(NSError *)error
{
UIAlertView *objAlert = [[UIAlertView alloc] init];
[objAlert setTitle:#"Internet Connection"];
[objAlert addButtonWithTitle:#"Ok"];
if([error code] == -1001 || [[error localizedDescription] isEqualToString:#"timed out"]){
[objAlert setMessage:#"Request Timed Out."];
[objAlert show];
}
}

Add Pop-up for database update

I'm a new iphone developer and getting ready to launch my first app. I have an reference utility app that I developed with help from an experienced developer to provide a process to upload database update to SQLite from access. When the updates occur, I have a popup window appearing which prompts the user to accept the data update or not. However, if they accept the update I want a popup to display during the update process. What do I need to do to ad this to this code?
if( [elementName isEqualToString:#"is_update_availableResult"] )
{
if([soapResults isEqualToString:#"yes"])
{
soapResults = [[NSMutableString alloc] init];
NSString *strMessage=#"An update is available. Select OK to update or cancel to load later. Please wait while system loads data before using app. ";
altView=[[UIAlertView alloc] init];
altView.title=#"MY APP";
altView.delegate=self;
[altView addButtonWithTitle:#"OK"];
[altView addButtonWithTitle:#"Cancel"];
[altView setCancelButtonIndex:0];
altView.message=strMessage;
[altView show];
}
Use the below code to implement the progress indication for your data base operation.
Declare UIAlertView* myAlert in your class header file.
myAlert = [[UIAlertView alloc] initWithTitle:#"Updating database…" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[myAlert show];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.center = CGPointMake(myAlert.bounds.size.width / 2, myAlert.bounds.size.height - 50);
[indicator startAnimating];
[myAlert addSubview:indicator];
[indicator release];
Once your database operation is completed dismiss the UIAlertView
-(void) OperationCompleted
{
[myAlert dismissWithClickedButtonIndex:0 animated:YES];
}

NSTask waitUntilExit hanging app on jailbroken iOS

So I've got NSTask to run a script which generates a list of something, into a txt, which I read from. But if I use my current code (below), the alert pops up before the NSTask is finished, thus resulting in a blank alert. I've tried waitUntilExit but that makes the button that invokes this action freeze, but the UI doesn't lock up itself.
- (void) runSupported {
stask = [[NSTask alloc] init];
[stask setLaunchPath:#"/bin/bash"];
NSString *script;
script = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:#"/apps.sh"];
NSArray *sargs = [NSArray arrayWithObjects:script, #"-txt", nil];
[stask setArguments: sargs];
[stask launch];
NSString *apps;
apps = [NSString stringWithContentsOfFile:#"/var/mobile/supported.txt" encoding:NSUTF8StringEncoding error:nil];
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:apps]) {
UIAlertView *supported = [[UIAlertView alloc] initWithTitle:#"App List" message:apps delegate:self cancelButtonTitle:#"Ok!" otherButtonTitles:nil];
[supported show];
[supported release];
} else {
UIAlertView *supported = [[UIAlertView alloc] initWithTitle:#"App List" message:#"Error generating list." delegate:self cancelButtonTitle:#"Ok!" otherButtonTitles:nil];
[supported show];
[supported release];
}
}
Any idea how I'd have the NSTask finish before invoking the alert? Thanks.
Edit: Code with NSNotification:
-(IBAction) supported {
stask = [[NSTask alloc] init];
[stask setLaunchPath:#"/bin/bash"];
NSString *script;
script = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:#"/apps.sh"];
NSArray *sargs = [NSArray arrayWithObjects:script, #"-txt", nil];
[stask setArguments: sargs];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(taskEnded:)
name: NSTaskDidTerminateNotification
object: nil];
[stask launch];
}
- (void)taskEnded:(NSNotification *)notification {
if (stask == [[notification object] terminationStatus]) {
NSString *apps;
apps = [NSString stringWithContentsOfFile:#"/var/mobile/supported.txt" encoding:NSUTF8StringEncoding error:nil];
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:apps]) {
UIAlertView *supported = [[UIAlertView alloc] initWithTitle:#"Apps" message:apps delegate:self cancelButtonTitle:#"Ok!" otherButtonTitles:nil];
[supported show];
[supported release];
} else {
UIAlertView *supported = [[UIAlertView alloc] initWithTitle:#"Apps" message:#"Error generating list." delegate:self cancelButtonTitle:#"Ok!" otherButtonTitles:nil];
[supported show];
[supported release];
}
} else {
NSLog(#"Task failed.");
}
}
Don't use waitUntilExit.
The problem is how to do something after the task finishes without blocking the UI (or freezing that one button). The solution, as for all similar problems, is to be notified when the task finishes, and proceed further (show the alert) in response to that notification.
The notification, in this case, is an NSNotification named NSTaskDidTerminateNotification. When the task exits, for any reason, the NSTask object will post this notification on the default NSNotificationCenter. You can ask the task what its termination status was to determine whether it succeeded, failed, or crashed.
See also: Notification Programming Topics.
Have a look at AMShellWrapper which is based on Apple's Moriarity sample code.
"Connect your own methods to stdout and stderr, get notified on process termination and more."
See: http://www.cocoadev.com/index.pl?NSTask
Don't use waitUntilExit on your main thread. That will block your UI, and freeze your app.
You need to subscribe to the notification NSTaskDidTerminateNotification, which is posted when the task has stopped execution:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(taskDidTerminate:)
name:NSTaskDidTerminateNotification
object:nil];
Note that the notification can be posted if the task completed normally, or as the result of a terminate message:
- (void) taskDidTerminate:(NSNotification *)notification {
if (YOUR_TASK_SUCCESS_VALUE == [[notification object] terminationStatus]) {
NSLog(#"Task succeeded.");
// Here you can add your checks on the creation on the files and user alerts confirmation
} else {
NSLog(#"Task failed.");
}
}
Don't forget to unsubscribe to the notification ; depending on where you subscribe to the notification, a good place would be in your dealloc method:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Update: You expect something that is documented on Mac to work the same on iOS, where it is not documented. Not really surprised it doesn't work.
Have you tried to execute the task - and use the waitUntilExit method - in a background thread?
If you are lucky and it works, don't forget to switch back to the main thread when showing your UIAlert.