Iphone NSURLConnection不';在iOS5中创建多个下载对象时无法接收数据
我已经在SOF上搜索这个问题好几天了,但我仍然没有找到解决方案(比如说相同的问题) 我正在制作一个应用程序,可以在一个URL列表中同时下载5个图像(每个图像位于不同的服务器上) 我有一个Iphone NSURLConnection不';在iOS5中创建多个下载对象时无法接收数据,iphone,ios,objective-c,ios5,nsurlconnection,Iphone,Ios,Objective C,Ios5,Nsurlconnection,我已经在SOF上搜索这个问题好几天了,但我仍然没有找到解决方案(比如说相同的问题) 我正在制作一个应用程序,可以在一个URL列表中同时下载5个图像(每个图像位于不同的服务器上) 我有一个ImageDownloader类子类NSOperation,并实现了NSURLConnectionDataDelegate 这样我就可以将ImageDownloader的实例添加到ViewController中的operationQueue中,它将在operationQueue下的单独线程中运行。将下载程序添加到
ImageDownloader
类子类NSOperation
,并实现了NSURLConnectionDataDelegate
这样我就可以将ImageDownloader
的实例添加到ViewController
中的operationQueue
中,它将在operationQueue
下的单独线程中运行。将下载程序添加到操作队列的行如下所示:
downloader = [[ImageDownloader alloc] init];
[downloader downloadImageWithURL:[controller.URList objectForKey:[NSString stringWithFormat:@"%d",downloadIndex]] queue:queue andTag:downloadIndex + 100]; //my custom initialize
downloader.delegate = self;
[queue addOperation:downloader]; //use the addOperation method
在iOS6中一切正常,但在iOS5中一切都一团糟(在我的测试设备上是5.0,在我的SDK上是5.1),通过执行方法didReceiveResponse
和didReceiveData
,它根本没有收到任何响应或数据(这两种方法都没有加入)
超过超时后,runloop跳转到didFailWithError
方法,程序暂停
据我所知,这意味着runloop仍然运行正常
我试图打印出错误
,但得到的结果是:请求超时
当我将下载实例的数量减少到2时,它将运行,但不包括>=3个下载实例
还有一个信息是,我的网络连接确实限制了连接的数量。但是它在iOS6中工作得很好,为什么它在iOS5上不工作呢
当应用程序下载时,我仍然可以在模拟器中加载web
那么这是什么样的问题?我如何克服这个问题
提前谢谢
*更新:因为有很多类,而且问题还没有被明确发现,所以我将在这里分享整个项目。您可以直接从此处下载:
正如我刚刚发现的,如果您使用的是凭据,服务器有可能会偶尔随机拒绝它们。因此,如果您有一个检查来确保previousFailureCount==0,那么您很可能有一个bug。我刚刚找到了问题所在,但并不真正理解原因
在我的ImageDownloader
类中,我使用done
和currentRunLoop
变量设置了一个运行循环。
在main方法中,我有一个while循环,用于强制运行currentRunLoop
run
当我删除那些“runLoop”内容时,应用程序在iOS6和iOS5上都能顺利运行
因此,用这些行更改整个ImageDownloader.m
,然后它就可以工作了(我注释掉了一些无用的(比如有害的)行):
谢谢你们的支持
========================================================================================================================================
p/s:对于任何对此问题感兴趣的人,我在此更新我的整个解决方案:打开并行连接是有限制的。检查我建议使用AFNetworking而不是本机NSURLConnection,这可能会很乏味。我刚刚更新了我的问题。@KishoreK:图像在不同的服务器上。我认为5台不同服务器的5个并发连接并没有什么危险。@Lynayo:我想靠自己来深入理解这个问题,所以我不想在我的应用程序中使用任何库(我下载并在5.1模拟器上运行了它,它成功了。也许解决方案是将你的目标操作系统设置为5.1并暂停一天?只是一个简单的回答,不知道是否是这样,但我以前在iOS 5上也有相同的机制,即一个队列持有同步下载操作,并发数量有限。这导致了很多问题。)ms当队列中充满了等待轮到它的许多请求时,这导致超时和其他不可预测的网络错误,所有这些都具有很好的“随机性”。我很快就摆脱了它,并在UIViewController使用的自定义下载控制器的帮助下直接启动异步下载。感谢您的支持回答,但我还不知道你的想法。请详细解释一下!我正在做以下操作。看起来你没有,所以…你可能没有这个问题。-(无效)连接:(NSURLConnection*)连接确实收到了AuthenticationChallenge:(NSURAuthenticationChallenge*)挑战{if(_-credential&&challenge.previousFailureCount==0){[[challenge sender]useCredential:_-credential for-authenticationchallenge:challenge];}是的,我没有这个问题。谢谢。我只是看了一下你的项目。有两件事:1.你没有正确地继承NSOperation。2.你没有正确地使用NSOperation。3.你最好将运行循环封装到NSOperation子类中(使用主线程或带有运行循环的专用线程).4.一些设计问题。因此,基本上,代码不起作用。我建议,阅读有关NSOperation和如何正确子类的文档。作为一个跳转,请查看Apple示例(MVCNetworking)中的QHTTPOperation
。另一个跳转起点:Gist上有一个简单的示例,它定义了一个类SimpleGetTTPrequest
,封装了NSURLConnection
和相关的状态信息。它可以很容易地修改为NSOperation
的子类。它是专门为用户设计的,让他们知道如何创建自己的“HTTPRequestOperation”类并已稳步改进。祝您玩得开心;)代码中的另一个问题:在addDownloadProcess:
中,您将调度到dispatchQueue(可能不是主队列)块调用downloadImageWithURL:
。后一种方法然后在当前线程的运行循环上调度委托。但是,调度队列的当前线程未指定,很可能是h
//
// ImageLoader.m
// DownloadImagesTableView
//
// Created by Viet Ta Quoc on 6/25/13.
// Copyright (c) 2013 Viet Ta Quoc. All rights reserved.
//
#import "ImageDownloader.h"
@implementation ImageDownloader
@synthesize downloadData,delegate,queue,done,customTag;
NSRunLoop *currentRunLoop;
-(void)downloadImageWithURL:(NSString *)imageUrl queue:(NSOperationQueue*)opQueue andTag:(int)tag{
self.customTag= tag;
self.queue = opQueue;
// self.done = NO;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:imageUrl] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[connection start];
// currentRunLoop = [NSRunLoop currentRunLoop];
NSLog(@"Start downloading image %d...",customTag);
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(@"Received response...");
downloadData=[[NSMutableData alloc] initWithLength:0];
expectedDataLength=[response expectedContentLength];
NSLog(@"Image %d size: %lld kb",customTag,[response expectedContentLength]/1024);
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
float receivedLenght = [data length];
receivedDataLength=(receivedDataLength+receivedLenght);
float progress=(float)receivedDataLength/(float)expectedDataLength;
[delegate updateProgess:progress andIndex:[NSIndexPath indexPathForRow:customTag-100 inSection:0]];
[self.downloadData appendData:data];
// NSLog(@"Percentage of data received of tag %d: %f %%",self.customTag,progress*100);
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
[delegate finishedDownloadingImage:downloadData andTag:customTag];
// done = YES;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Warning" message:@"Network Connection Failed?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
// NSLog(@"%@",[error debugDescription]);
NSLog(@"Connection failed! Error - %@ %@",[error localizedDescription],[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
[alert show];
}
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
NSLog(@"Got here *(*&(**&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&(*&");
}
-(void)main{
// do{
//// NSLog(@"Running....1");
// [currentRunLoop runUntilDate:[NSDate distantFuture]];
// // [currentRunLoop run];
// } while (!done);
// [currentRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
@end