setDelegate self并在ASINetworkQueue中使用委托。请求完成后找不到选择器

时间:2014-01-16 20:09:59

标签: ios objective-c asihttprequest

我有以下课程:

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

}

在另一个类中,函数被称为内部函数,我正在执行以下操作:

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

一切正常,下载开始。但是当下载第一个文件时,我在ASINetworkQueue类中得到一个错误,我的选择器“requestFinished”无法被调用(我没有确切的消息,此刻无法启动应用程序,但失败代码是exc_bad_access code = 1)。

我的File_Downloadmanager对象的声明/初始化时间是否存在问题?因为调用了函数“downloadFiles”,所以创建了DownloadManager对象,添加了请求,然后返回“downloadFiles”方法,因为队列工作异步?

2 个答案:

答案 0 :(得分:1)

看起来ASINetworkQueue试图发送requestFinished消息的downloadhandler对象在消息发送给它时不再存在,因为当downloadFiles方法完成执行时它可能被解除分配。而不是将downloadhandler对象设置为downloadFiles方法的本地,而是使其成为包含downloadFiles方法的类中的(强大的,非原子的)属性。这样,您可以确保在调用requestFinished时它仍然存在。

答案 1 :(得分:1)

之前我没有使用ASI网络的东西,但在网上看到了很多对它的引用。

听起来像ASINetworkQueue类要求它的委托符合特定协议。如果设置正确,当您尝试将自己指定为ASINetworkQueue对象的委托但未声明您的类符合相应的协议时,您应该收到警告。如果您要包含协议声明,那么您应该收到一条警告,指出您尚未从该协议实现所需的方法。

尝试清理项目并重建,然后仔细查看警告,特别是在您的行上:

[[self downloadQueue] setDelegate:self];
编辑:我刚刚下载了一个ASIHTTPRequest项目,令我沮丧的是,ASINetworkQueue类的委托属性不必符合特定协议。这是糟糕的编程风格。如果设置了委托,则应使委托指针符合特定协议。

另外,请注意,ASI网络类现在已经维护了几年并且已经过时了。有更好的替代方案,你应该考虑转向不同的网络框架。