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

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];
}
}

Related

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

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.

XMPPFramework not sending presence

Im developing an app for iPhone, in wich one of the functionalities is an instant message system, using XMPPFramework. By now, im testing it with Google Talk. The delegate is the same class that manages the User Interface. So, I got this code:
In viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupStream];
}
The setupStream method:
- (void) setupStream
{
NSLog(#"Inside setupStream");
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[self connect];
}
The connect method:
- (BOOL) connect
{
NSLog(#"Inside connect method");
General *general = [General sharedManager];//this is a singleton to manage settings for every user
NSString *chatid;
NSString *chatpass;
//chatid=[general user];
chatid=#"somegmailaccount#gmail.com";
xmppStream.myJID=[XMPPJID jidWithString:chatid];
if (![xmppStream isDisconnected]) {
return YES;
}
NSError *error = nil;
if (![xmppStream connect:&error])
{
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;
}
In xmppStreamDidConnect method:
- (void) xmppStreamDidConnect:(XMPPStream *)sender
{
[xmppStream authenticateWithPassword:#"password" error:NULL];
[self goOnline];
}
And goOnline method:
- (void) goOnline
{
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
NSLog(#"Presence sent");
}
With this, the presence is not sent. I have another google account that I try for testing (say, testing#gmail.com) and in this account the presence of somegmailaccount.gmail.com is not seen. Both accounts are connected and know each other, since I used this same accounts to develop the Android app.
Any idea about what i´m doing wrong? Any help is appreciated.
Thank you very much.
I found it! The presence is not sent this way:
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
Insted, i have done it this way:
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
[xmppStream sendElement:presence];
This way, the presence is sent without any problem :)
With this code, i implement method xmppStreamDidAuthenticate:(XMPPStream *)sender
and the program DO enter that method without any call from my code. But if i put
[xmppStream setHostName:#"talk.google.com"];
[xmppStream setHostPort:5222];
... in method connect, the program DO NOT enter that method, nor xmppStreamDidConnect.
Im getting mad.

Incrementing `static int` causes SIGSEGV SEGV_ACCERR

I'm debugging a crash reported as:
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR
The crash is happening on the line that does numberOfFails++.
The app uses ASIHTTP. I personally much prefer using NSURLConnection. I'd never automatically repeat a request for NSURLConnection if it failed because I've never seen it fail when it shouldn't. I'd rather just give the UI a refresh button or show a UIAlertView with a button to try again or something like that.
Anyway, to cooperate with other team members, I'm looking to fix this issue without replacing ASIHTTP with NSURLConnection for now.
The request is being started with something like:
- (void)getResources:(CLLocation *)location withQuery:(NSString *)query {
NSURL *url = [NSURL URLWithString:[NSString stringWithString:#"https://example.com/"]];
self.resourcesAPIRequest = [ASIFormDataRequest requestWithURL:url];
[resourcesAPIRequest setPostValue:[Model instance].oauth_token forKey:#"oauth_token"];
[resourcesAPIRequest setPostValue:[[NSNumber numberWithDouble:location.coordinate.latitude] stringValue] forKey:#"latitude"];
[resourcesAPIRequest setPostValue:[[NSNumber numberWithDouble:location.coordinate.longitude] stringValue] forKey:#"longitude"];
[resourcesAPIRequest setPostValue:query forKey:#"query"];
[resourcesAPIRequest setDelegate:self];
[resourcesAPIRequest setDidFinishSelector:#selector(resourcesAPIReturned:)];
resourcesAPIRequest.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:NSStringFromSelector(#selector(getResources:withQuery:)), #"repeatSelector", location, #"argument1", query, #"argument2", nil];
[resourcesAPIRequest startAsynchronous];
}
One thing I noticed is : <ASIHTTPRequestDelegate> is not in the header file, but this callback method is still being called OK:
#define maximumNumberOfFails 50
- (void)requestFailed:(ASIFormDataRequest *)request {
static int numberOfFails = 0;
if (numberOfFails < maximumNumberOfFails) {
[NSThread sleepForTimeInterval:sleepTimeInSeconds];
if ([request.userInfo objectForKey:#"argument2"]) {
[self performSelector:NSSelectorFromString([request.userInfo objectForKey:#"repeatSelector"]) withObject:[request.userInfo objectForKey:#"argument1"] withObject:[request.userInfo objectForKey:#"argument2"]];
} else if ([request.userInfo objectForKey:#"argument1"]) {
[self performSelector:NSSelectorFromString([request.userInfo objectForKey:#"repeatSelector"]) withObject:[request.userInfo objectForKey:#"argument1"]];
} else {
[self performSelector:NSSelectorFromString([request.userInfo objectForKey:#"repeatSelector"])];
}
numberOfFails++;
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Problem" message:#"There was a problem connecting to the servers. Please make sure you have an Internet connection." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
numberOfFails = 0;
}
}
Also, I think that static int numberOfFails should be static NSUInteger numberOfFails. And, I noticed that the request is started with startAsynchronous. Is static int numberOfFails atomic? That may be why we're getting the error SEGV_ACCERR (Invalid permissions for mapped object).
Thoughts?
The problem likely has nothing to do with your static variable.
Does requestFailed: execute on the main thread, or in a background thread?
If it's on a background thread, you'll need to use performSelectorOnMainThread:withObject:.
If it's on the main thread, you may need to take a pass through the runloop before executing a new HTTP request. To do that, use performSelector:withObject:afterDelay:, and pass '0.0' as the delay.
You'll notice that both those methods allow only a single method parameter. Typically, you pass your parameters in a NSDictionary rather than try to parse out the number of parameters beforehand, like you're doing.

using NSURLConnection instead of stringWithContentsOfURL

Guys, I was retrieving an XML response from a .php script on my server using the following code:
NSString *xmlString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString]
encoding:NSUTF8StringEncoding error:&error];
and
//tried also: if(error)
if(!xmlString)
{
NSString * errorString = [NSString stringWithFormat:#"Unable to download xml data (Error code %i )", [error code]];
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
}
//*** now I have a touchXML xPath query code that extracts what I need from XML
My .php script wasn't working today and my iApp was freezing without any alerts, errors or notifications? I thought that the code above will handle errors but it doesn't???
A) Then what type of error does it catch?
Then I remembered that i I should try working with NSURLConnection and its delegate methods to catch any error that occurs.
//Inside viewDidLoad method
NSMutableData *responseData = [[NSMutableData alloc] init];
NSURL *baseURL = [[NSURL URLWithString:self.chosenDrawRss] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:baseURL];
[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
NSString *xmlString = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
The problem I had using this approach was that app ran the Connection in the background and continued executing the rest of the code found in viewDidLoad, so I had to reorganize my code a bit by moving it to another method that I call from delegate method connectionDidFinishLoading. The problem I have is that my delegate methods are not called. Well, all except didFailWithError: if I try to load URL that doesn't exist.
UPDATE:
delegate methods are called but it takes one minute or so for delegate method to be called and until alert message pops out...
B) Could I use stringWithContentsOfURL and still have an alert to the user if anything happens?
C) If not, then I need help with setting up NSURLConnection approach? I mean, what I'm missing here is why aren't my delegate methods called?
I truly hope my questions make sense :D
L
If your delegate method is called in didFailWithError then i suppose it will even be called in
connectionDidFinishLoading. Check by enabling a breakpoint in the delegate methods and track the flow. It may have happened the function returns before you call the delegate.
NSString *xmlString = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding]
should be called in your delegate connectionDidFinishLoading method and in
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
I dont see why the alert should pop up after a minute unless you are doing some processing before displaying it.

How to show an alert when the server is not working properly?

I am getting list using url by doing parsing it using xml parser. sometimes the server is not working properly. then how to give an alert when server is not working properly. I have given the code below
-(NSMutableArray*)getCustomerList:(NSString *)count category:(NSString *)aCategory alphabetic:(NSString *)alphabeticValue favorite:(NSString *)isFavoriteString
{
[self updateStatus];
if (internetConnectionStatus == NotReachable)
{
UIAlertView *reachbleAlert = [[UIAlertView alloc] initWithTitle:#"message"
message: #"No network available alert"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[reachbleAlert show];
[reachbleAlert release];
return 0;
}
else
{
NSString *urlString=#"http:getCustomerList.jsp";
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[dataParser parseXMLFileAtURL:[NSURL URLWithString:urlString]];
NSMutableArray *list =[dataParser getCustomerListFromParser];
printf("\n url for Customer List%s",[urlString UTF8String]);
printf("\n Customer List %d",[list count]);
return list;
}
}
I am sending parameter to url to return repctive list when it returns zero I am dispalying alert in view controller.
but when server is not working properly then how to display this alert.
Please help me out of this.
Thank you,
Madan mohan.
In my opinion :
First perform the request operation to the server for any response.
Secondly Catch the the response received in a BOOL variable .
Finally when your BOOL variable is TRUE perform the desired operation [Such as parsing..]
Otherwise just show an alert message with a proper error message.
I'm sure there's a perfectly nice way to do it with parseXMLFileAtURL. I don't that way.
What I do know is if you use the excellent ASIHTTPRequest library to make an asynchronous request, all of that stuff is taken care of for you. You create two delegate methods, RequestFinished and RequestFailed, and one of them will be called when the result is clear.
In RequestFinished you'd parse the string portion of the response object.
In RequestFailed you'd display the alert and then decide how to proceed from there.
for this u create the asynchronous request usingNSURLRequest
NSURL *theURL=[[NSURL alloc]initWithString:#"**YOUR URL**"];
NSMutableURLRequest *theRequest = [[NSMutableURLRequest alloc] initWithURL:theURL];
[theRequest setTimeoutInterval:150];
[theURL release];
mURLConnection=[[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
[theRequest release]
and then in their delegate method
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (mResultData == nil) //mResultData is NSData(member variable)
mResultData = [[NSMutableData alloc] init];
[mResultData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mResultData appendData:data];
}
// this method calls if their is any problem from server side
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[mResultData release];
mResultData = nil;
[mURLConnection release];
mURLConnection = nil;
//here the show the error
UIAlertView *theAlert=[[UIAlertView alloc]initWithTitle:kAlertTitle message:[error localizedDescription] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[theAlert show];
[theAlert release];
}
(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//here u could send mResulData for parsing
// create NSXMLParser
}