ASIHTTPRequest: Receive delegates from several requests within a network queue - iphone

I use ASINetworkQueue to send two requests, which are in a queue.
My problem is, that I'm not able to receive notifications when
a request fails/is done.
Code:
[networkQueue cancelAllOperations];
[networkQueue setShowAccurateProgress:YES];
[networkQueue setUploadProgressDelegate:self.progressIndicator];
[networkQueue setDelegate:self];
[networkQueue setQueueDidFinishSelector:#selector(queueDidFinish)];
NSURL *urlAttachment = [NSURL URLWithString:#"http://localhost/test1.xml"]];
ASIFormDataRequest *requestFile = [[[ASIFormDataRequest alloc] initWithURL:urlAttachment] autorelease];
[requestFile setFile:filePath forKey:#"attachment[test]"];
[requestFile setDidFailSelector:#selector(test1WentWrong)];
[requestFile setDidFinishSelector:#selector(test1Done)];
[networkQueue addOperation:requestFile]; //queue is an NSOperationQueue
NSURL *url = [NSURL URLWithString:#"http://localhost/test2.xml"]];
ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:test.filename forKey:#"filename[test]" ];
[request setDidFailSelector:#selector(test2WentWrong)];
[request setDidFinishSelector:#selector(test2Done)];
[networkQueue addOperation:request]; //queue is an NSOperationQueue
[networkQueue go];
test1WentWrong, test1Done, test2WentWrong, test2Done aren't called.
Although the request runs fine and queueDidFinish gets called.

You need to set the delegate of the individual requests rather than the queue.
Basically, if you set the didFinish and didFail selectors on the queue, the queue's delegate is called. If you set them on the request, the request's delegate is called (You can also do both, in which case both get called).
In your case, where you want to use the same delegate for both requests, but different selectors for didFail / didFinish, I can see it would make sense for the queue's delegate to be called if you didn't set a delegate for the request. Perhaps I should add this... :)
Ben

Related

ASIHTTPRequest Request Cancel

I have been using ASIHTTPRequest to fetch the data and i want to cancel the request how i do it??
i do the code just like this..
-(void) serachData{
NSURL *url= [NSURL URLWithString:self.safestring];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setTimeOutSeconds:7200];
[request setDelegate:self];
[request startAsynchronous];
}
- (NSMutableDictionary *)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"requestFinished");
NSString *responseString = [request responseString];
SBJsonParser *json = [[SBJsonParser alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects[jsonobjectWithString:responseString], nil];
NSLog(#"array %#",array);
}
- (void)requestFailed:(ASIHTTPRequest *)request{
NSLog(#"requestFailed");
}
//if i press cancel button(when requestFinished /requestFailed method in process ) then the ASIHTTPRequest fail and finish method Stop /abort! how i do this??
-(IBAction)CancleREquest:(id)sender{
NSLog(#"CancleREquest");
}
Your cancel specific ASIHTTPRequest then :
if(![yourASIHTTPRequest isCancelled])
{
// Cancels an asynchronous request
[yourASIHTTPRequest cancel];
// Cancels an asynchronous request, clearing all delegates and blocks first
[yourASIHTTPRequest clearDelegatesAndCancel];
}
Note : To cancel all ASIHTTPRequest then :
for (ASIHTTPRequest *request in ASIHTTPRequest.sharedQueue.operations)
{
if(![request isCancelled])
{
[request cancel];
[request setDelegate:nil];
}
}
EDIT : Use AFNetworking as ASIHTTPRequest is deprecated as its has not been update since march 2011.
Nice simple version:
for (ASIHTTPRequest *request in ASIHTTPRequest.sharedQueue.operations){
[request cancel];
[request setDelegate:nil];
}
I suggest you to keep a reference to the pending request in an ivar/property of your controller, then send the cancel message to it from your button handler.
//-- in your class interface:
#property (nonatomic, assign) ASIFormDataRequest *request;
....
//-- in your class implementation:
#synthesize request;
.....
-(void) serachData{
NSURL *url= [NSURL URLWithString:self.safestring];
self.request = [ASIFormDataRequest requestWithURL:url];
[self.request setTimeOutSeconds:7200];
[self.request setDelegate:self];
[self.request startAsynchronous];
}
-(IBAction)CancleREquest:(id)sender{
[self.request cancel];
NSLog(#"request Canceled");
}
You have several options when canceling, though; from ASIHTTPRequest docs:
Cancelling an asynchronous request
To cancel an asynchronous request (either a request that was started with [request startAsynchronous] or a request running in a queue you created), call [request cancel]. Note that you cannot cancel a synchronous request.
Note that when you cancel a request, the request will treat that as an error, and will call your delegate and/or queue’s failure delegate method. If you do not want this behaviour, set your delegate to nil before calling cancel, or use the clearDelegatesAndCancel method instead.
// Cancels an asynchronous request
[request cancel]
// Cancels an asynchronous request, clearing all delegates and blocks first
[request clearDelegatesAndCancel];

ASINetworkQueue delegate method not called

In my application i am using ASINetworkQueue method for downloading files. I have n number of buttons and for each button click different Queues will be created with multiple Requests, and starts download asynchronously (multiple download). It is working fine, but I couldn't track when each Queue completes. I have used,
[self.myQueue cancelAllOperations];
[self.myQueue setDownloadProgressDelegate:currentProgress];
[self.myQueue setDelegate:self];
[self.myQueue setShowAccurateProgress:YES];
[self.myQueue setRequestDidFinishSelector:#selector(requestFinished:)];
[self.myQueue setQueueDidFinishSelector:#selector(queueComplete:)];
and added requests as,
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:str]];
[request setDownloadProgressDelegate:currentProgress];
[request setShowAccurateProgress:YES];
[request setDelegate:self];
[request shouldContinueWhenAppEntersBackground];
[request allowResumeForFileDownloads];
[request startAsynchronous];
[self.myQueue addOperation:request];
and last, [self.myQueue go];
and the delegate method is
- (void)queueComplete:(ASINetworkQueue *)queue
{
NSLog(#"Queue completed");
}
but its not called at the end. What went wrong here? Any idea?
And also, if there are multiple Queues performing at the same time, how can we differentiate which queue is completed at the end?
Edit:
- (void)download{
UIImageView *image = (UIImageView *)[mainView viewWithTag:selectedTag];
for (UIProgressView *currentProgress in [image subviews]) {
if ([currentProgress isKindOfClass:[UIProgressView class]]) {
NSLog(#"Prog tag: %d",currentProgress.tag);
if(currentProgress)
{
currentProgress.progress = 0.0;
[[self myQueue] cancelAllOperations];
[self setNetworkQueue:[ASINetworkQueue queue]];
[[self myQueue] setDownloadProgressDelegate:currentProgress];
[[self myQueue] setDelegate:self];
[[self myQueue] setShowAccurateProgress:YES];
ASIHTTPRequest *request;
[myQueue setQueueDidFinishSelector:#selector(queueComplete:)];
for (int h = 0; h < [urlArray count]; h++) {
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:[urlArray objectAtIndex:h]]];
[[self myQueue] addOperation:request];
}
[[self myQueue] go];
}
}
}
}
You are starting the request before adding it to the queue.
[request startAsynchronous];
The starting of the request should only be handled by the queue. So remove that line and the complete callback should be called.
When you have more than one queue, you should keep a reference to each queue. You could put them in an NSMutableArray. Then in the complete callback you can check which queue is complete by checking them against the queues in your array.
EDIT:
It seems that you forget to set your myQueue iVar, so it was nil and ignored all method calls. So add:
self.myQueue = [ASINetworkQueue queue];
To have more than one queue in an array:
self.queues = [NSMutableArray array] // queues is a retained property
ASINetworkQueue *queue = [ASINetworkQueue queue];
[queues addObject:queue];

Canceling a ASIHTTPRequest - Beginner

I am using ASIHTTPRequest to send request to web server. It all works fine. But now, when i call the grabURLInBackground method, a request is sent to the given URL.
But now, i need to cancel the request (as in stop sending, and stop downloading the content from the URL), in the viewWillDissapear method. How can i do this ? Help
- (IBAction)grabURLInBackground:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
for (ASIHTTPRequest *req in ASIHTTPRequest.sharedQueue.operations)
{
[req cancel];
[req setDelegate:nil];
}
this should cancel it..
You can do:
[request cancel]
Or:
[request clearDelegatesAndCancel];
As can be seen in the documentation here.
I'd suggest storing a reference to that request so you can cancel it when leaving the view.
GOt thsi from ASIHttp docs:
Cancelling an asynchronous request
To cancel an asynchronous request (either a request that was started with [request startAsynchronous] or a request running in a queue you created), call [request cancel]. Note that you cannot cancel a synchronous request.
Note that when you cancel a request, the request will treat that as an error, and will call your delegate and/or queue’s failure delegate method. If you do not want this behaviour, set your delegate to nil before calling cancel, or use the clearDelegatesAndCancel method instead.
// Cancels an asynchronous request
[request cancel]
// Cancels an asynchronous request,
clearing all delegates and blocks first
[request clearDelegatesAndCancel];When using an ASINetworkQueue, all other requests will be cancelled when you cancel an individual request unless the queue’s shouldCancelAllRequestsOnFailure is NO (YES is the default).
// When a request in this queue fails or is cancelled, other requests will continue to run
[queue setShouldCancelAllRequestsOnFailure:NO];
// Cancel all requests in a queue
[queue cancelAllOperations];

Getting SIGABRT with ASINetworkQueue due to Threading

I've been getting SIGABRT when using ASINetworkQueue, and I've a suspicion that its related to threading and I'm not sure what or why. If I comment out the following code everything works, but if I leave it in, the app will just stop with a SIGABRT and no other information.
// create ASINetwork queue
if (networkQueue == nil)
{
networkQueue = [ASINetworkQueue queue];
[networkQueue setDelegate:self];
[networkQueue setRequestDidFinishSelector:#selector(requestFinished:)];
[networkQueue setRequestDidFailSelector:#selector(requestFailed:)];
[networkQueue setQueueDidFinishSelector:#selector(queueFinished:)];
[networkQueue retain];
}
// if branding url available
if ([brandingURL length] > 0) {
NSString *stringURL = [NSString stringWithFormat:#"%#/admin%#", SERVER_BASE_URL, brandingURL];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:stringURL]];
[request setUserInfo:[NSDictionary dictionaryWithObject:#"branding" forKey:#"requestType"]];
[networkQueue addOperation:request];
}
[networkQueue go];
The thread listing is in the following image gallery which is the only thing which might shed some light on whats going on with the threads.
http://imgur.com/a/msp8x
Any advice or suggestions much welcome.

ASIHTTP: addOperation when other threads are running

I have a project using ASIHTTP to multi download files from a site
when I add a new request:
[networkQueue cancelAllOperations];
[networkQueue setDownloadProgressDelegate:a];
[networkQueue setDelegate:self];
[networkQueue setRequestDidFinishSelector:#selector(requestDone:)];
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
[networkQueue addOperation:request];
[networkQueue go];
it reported:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[ASINetworkQueue addOperation:]: operation is executing and cannot be enqueued'
It looks like I can not add a new request when others are running.
Welcome any comment
Thanks
interdev
If you are using a network queue, you cannot start the operation before you enqueue it. Don't call startAsynchrnous, just enqueue the operation and the network queue will start it when it dequeues it. Pretty much exactly what your error message says ;)
just remove the [request startAsynchronous]; and it will work fine for you.
hope this helps.
Thanks.