我有以下课程:
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”方法,因为队列工作异步?
答案 0 :(得分:1)
看起来ASINetworkQueue试图发送requestFinished消息的downloadhandler对象在消息发送给它时不再存在,因为当downloadFiles方法完成执行时它可能被解除分配。而不是将downloadhandler对象设置为downloadFiles方法的本地,而是使其成为包含downloadFiles方法的类中的(强大的,非原子的)属性。这样,您可以确保在调用requestFinished时它仍然存在。
答案 1 :(得分:1)
之前我没有使用ASI网络的东西,但在网上看到了很多对它的引用。
听起来像ASINetworkQueue类要求它的委托符合特定协议。如果设置正确,当您尝试将自己指定为ASINetworkQueue对象的委托但未声明您的类符合相应的协议时,您应该收到警告。如果您要包含协议声明,那么您应该收到一条警告,指出您尚未从该协议实现所需的方法。
尝试清理项目并重建,然后仔细查看警告,特别是在您的行上:
[[self downloadQueue] setDelegate:self];
编辑:我刚刚下载了一个ASIHTTPRequest项目,令我沮丧的是,ASINetworkQueue类的委托属性不必符合特定协议。这是糟糕的编程风格。如果设置了委托,则应使委托指针符合特定协议。
另外,请注意,ASI网络类现在已经维护了几年并且已经过时了。有更好的替代方案,你应该考虑转向不同的网络框架。