setDelegate self and using delegates in ASINetworkQueue. Selector not found when request finished

StackOverflow https://stackoverflow.com/questions/21171840

  •  28-09-2022
  •  | 
  •  

Question

I have the following class:

File_Downloadmanager.h:

#import "ASINetworkQueue.h"

@interface File_Downloadmanager : NSObject {

}
-(void)addRequestToDownloadQueue:(NSString*)objectID :(NSString*)userID :(NSString*)filename;
-(void)initDownloadQueue; // creates a new download queue and sets delegates
-(void)startDownload; // starts the download queue
-(void)requestFinished;
-(void)requestFailed;
-(void)queueFinished;


@property(retain) ASINetworkQueue *downloadQueue;

@end

File_Downloadmanager.m:

@implementation File_Downloadmanager

@synthesize downloadQueue;


-(void)initDownloadQueue{
    NSLog(@"Init DownloadQueue");
    // Stop anything already in the queue before removing it
    [[self downloadQueue] cancelAllOperations];


    [self setDownloadQueue:[ASINetworkQueue queue]];
    [[self downloadQueue] setDelegate:self];
    [[self downloadQueue] setRequestDidFinishSelector:@selector(requestFinished:)];
    [[self downloadQueue] setRequestDidFailSelector:@selector(requestFailed:)];
    [[self downloadQueue] setQueueDidFinishSelector:@selector(queueFinished:)];

    [self downloadQueue].shouldCancelAllRequestsOnFailure = NO;

}

-(void)startDownload{
     NSLog(@"DownloadQueue Go");
    [downloadQueue go];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    // If no more elements are queued, release the queue
    if ([[self downloadQueue] requestsCount] == 0) {
        [self setDownloadQueue:nil];
    }

    NSLog(@"Request finished");
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
    // You could release the queue here if you wanted
    if ([[self downloadQueue] requestsCount] == 0) {
        [self setDownloadQueue:nil];
    }

    //... Handle failure
    NSLog(@"Request failed");
}


- (void)queueFinished:(ASINetworkQueue *)queue
{
    // You could release the queue here if you wanted
    if ([[self downloadQueue] requestsCount] == 0) {
        [self setDownloadQueue:nil];
    }
    NSLog(@"Queue finished");
}

-(void)addRequestToDownloadQueue:(NSString*)objectID :(NSString*)userID :(NSString*)filename{

    ...SourceCode for creating the request...

        // add operation to queue
        [[self downloadQueue] addOperation:request];

}

In another class a function is called an inside that function I'm doing the following:

-(void)downloadFiles{
File_Downloadmanager * downloadhandler = [[File_Downloadmanager alloc]init];
// initialize download queue
[downloadhandler initDownloadQueue]; 

for (int i = 0; i < [meetingObjects count]; i++) {

....some other code to get the objectID, userID, etc.
 [downloadhandler addRequestToDownloadQueue:ID :[loginData stringForKey:@"userId"] :[NSString stringWithFormat:@"%@%@",currentObject.id,currentObject.name]]
}

[downloadhandler startDownload];
}

Everything works fine and the download begins. But when the first file is downloaded, I get an error in the ASINetworkQueue class that my selector "requestFinished" can't be called (I don't have the exact message, can't start the app at the moment, but the failure code was exc_bad_access code=1).

Is the time of declaration / initialization of my File_Downloadmanager object the problem? Because the function "downloadFiles" is called, the DownloadManager object created, the requests added and then the "downloadFiles" method returns because the queue works async?

Was it helpful?

Solution

I haven't used the ASI networking stuff before, but have seen lots of references to it on the net.

It sounds to me like the ASINetworkQueue class expects it's delegate to conform to a specific protocol. If it's set up correctly, you should get a warning when you try to assign yourself as the delegate of the ASINetworkQueue object but have not declared that your class conforms to the appropriate protocol. If you DO include a protocol declaration, then you should get a warning that you have not implemented required methods from that protocol.

Try cleaning your project and rebuilding, and then look carefully for warnings, specifically on your line:

[[self downloadQueue] setDelegate:self];

EDIT: I just downloaded one of the ASIHTTPRequest projects, and to my dismay, the delegate property of the ASINetworkQueue class does not have to conform to a specific protocol. This is bad programming style. If you set up a delegate, you should make the delegate pointer conform to a specific protocol.

Also, be aware that the ASI networking classes have not been maintained for several years now and are getting badly out of date. There are better alternatives out there, and you should look at moving to a different networking framework.

OTHER TIPS

It looks like the downloadhandler object that ASINetworkQueue is attempting to send the requestFinished message to no longer exists at the time that the message is sent to it, as it's probably being deallocated when the downloadFiles method finishes executing. Instead of making the downloadhandler object local to the downloadFiles method, instead make it a (strong, nonatomic) property within the class that contains the downloadFiles method. That way, you can ensure that it will still exist when requestFinished is called.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top