我在下载5 MB文件时遇到问题,在iPhone 5上使用iOS 6.1需要2分钟以上。
使用相同iOS版本的iPhone 4S仅需10秒,两者都使用WiFi。
我尝试了不同的缓存策略和NSURLRequest的超时间隔,它没有改变,它仍然需要很长时间。下载是通过HTTP。
我正在使用 NSURLConnection 类,在下载这个“大”文件之前我正在下载另外两个。
不知道还有什么可以重要,减少时间。
提前致谢。
代码:
@interface MyClass : NSObject <NSURLConnectionDelegate>
{
@private id delegate;
NSURLConnection *connection;
NSMutableData* responseData;
//...
}
#import "MyClass.h"
@implementation MyClass
-(void)getObj1:(id)delegateObj
{
delegate = delegateObj;
NSString *url = @"...";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:120.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(connection)
{
responseData = [NSMutableData data];
}
}
-(void)getObj2:(*String)somesString
{
NSString *url = @"...";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:120.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(connection)
{
responseData = [NSMutableData data];
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//....
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if(firstRequest)
{
//save data from first request and set responseData clear
[self getObj2:@"..."];
}
}
和其他没有什么特别的东西,我希望这已经足够了
我发现这篇文章https://devforums.apple.com/message/754875#754875,但对我来说仍然无效。但是现在我更好地理解这种奇怪的情况。
答案 0 :(得分:1)
使用AFDownloadRequestOperation(AFNetworking“sublass”) - 您也可以暂停/恢复操作。
答案 1 :(得分:0)
你试过AFNetworking
吗?它是NSURLConnection
的包装器。我不确定它是否能帮助您获得更快的下载速度,但它肯定能让您比NSURLConnection
更具优势。
答案 2 :(得分:0)
您使用GCD dispatch_async队列执行NSURLRequest请求集以从服务器下载数据或获取服务器响应。
NSString *webURL = @"http://therealurl.appspot.com/?format=json&url=bit.ly/a";
NSURL *url = [NSURL URLWithString:webURL];
NSURLRequest *awesomeRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:awesomeRequest delegate:self];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
NSRunLoop *loop=[NSRunLoop currentRunLoop];
[connection scheduleInRunLoop:loop forMode:NSRunLoopCommonModes];
//[self processTheAwesomeness];
});
答案 3 :(得分:0)
我建议一个解决方案,你有某种通信管理器,它有NSOperationQueue
处理,有一个入口点方法,你给它一个你要下载的内容的URL以及成功和失败的障碍。
通信管理器会创建一个NSOperation
来创建NSURLRequest
并处理回调。
一旦通信管理器将操作放入队列,就会调用其start
方法。
在我的通信管理器实现中,我通过NSMutableDictionary
跟踪(除了将操作放入队列之外)每个已启动的操作,以便您可以取消单个或所有操作(在示例代码中提供operationKey
用于此目的。JSONOperation
返回(如果成功)一个NSString到通信器但它也可以是任何类型的数据,例如我使用相同的类下载图像,所以我通过返回数据对象本身。
您可以在下面找到我的JSONOperation类作为示例。我喜欢我可以将其他文件放在Gist上的想法。
我的NSOperation
看起来像这样
@interface JSONOperation : NSOperation <NSURLConnectionDataDelegate, OperationDelegate>
+ (instancetype)jsonOperationForProvider:(id)provider success:(OperationSuccessWithString)success failure:(OperationFailure)failure;
@end
#import "JSONOperation.h"
#import "ProviderDelegate.h"
@interface JSONOperation()
@property (nonatomic, assign) BOOL executing;
@property (nonatomic, assign) BOOL finished;
@property (nonatomic, assign) BOOL cancelled;
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, weak) id <ProviderDelegate> delegate;
@property (nonatomic, strong) NSURLConnection *connection;
@property (nonatomic, strong) NSMutableData *receivedData;
@property (nonatomic, copy) OperationFailure failure;
@property (nonatomic, copy) OperationSuccessWithString success;
@end
@implementation JSONOperation
- (void)start
{
if ([self isCancelled])
{
[self willChangeValueForKey:@"isFinished"];
_finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
NSURLRequest *request = [NSURLRequest requestWithURL:self.url];
self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[self.connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[self.connection start];
[self willChangeValueForKey:@"isExecuting"];
_executing = YES;
[self didChangeValueForKey:@"isExecuting"];
}
- (NSMutableData *)receivedData
{
if (nil == _receivedData) {
_receivedData = [NSMutableData data];
}
return _receivedData;
}
+ (instancetype)jsonOperationForProvider:(id <ProviderDelegate>)provider success:(OperationSuccessWithString)success failure:(OperationFailure)failure
{
NSAssert(nil != provider, @"provider parameter can't be nil");
JSONOperation *operation = [[[self class] alloc] init];
operation.delegate = provider;
operation.url = provider.contentURL;
operation.failure = failure;
operation.success = success;
return operation;
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isExecuting {
return _executing;
}
- (BOOL)isFinished {
return _finished;
}
- (BOOL)isCancelled {
return _cancelled;
}
#pragma mark - NSURLConnectionDataDelegate
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (_success) {
NSString *receivedText = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding];
_receivedData = nil;
self.success(self, receivedText);
}
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
_executing = NO;
_finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[connection cancel];
_connection = nil;
_receivedData = nil;
_url = nil;
if (_failure) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.failure(self, error);
}];
}
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
_executing = NO;
_finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
#pragma mark - OperationDelegate
- (NSString *)operationKey
{
return [self.url absoluteString];
}
- (id)provider
{
return _delegate;
}
- (void)cancelOperation
{
_failure = nil;
_success = nil;
[self.connection cancel];
_connection = nil;
_receivedData = nil;
_url = nil;
[self willChangeValueForKey:@"isCancelled"];
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
_executing = NO;
_finished = YES;
_cancelled = YES;
[self didChangeValueForKey:@"isCancelled"];
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
@end
编辑 - Gist Sample files
答案 4 :(得分:0)
根据我的经验, AFNetworking 在处理下载方面做了很多工作。我正在对10 MB以上的文件使用下载操作。所以我强烈建议使用它。
My answer on stack to show progressbar。使用AFNetworking
和NSUrlconnection
查看我实现这两种方式的答案。您可以尝试两种方式并查看进度,并可以计算字节的获取方式在每个数据包中下载。通过跟踪它,您可以分析下载时间的变化情况。
试试吧
答案 5 :(得分:0)
尝试使用gzip
压缩NSURLRequest
的远程文件。它会大大加快您的连接速度。
要使用它,您需要在服务器上安装它,如果您在服务器上使用apache2
,那么好消息是默认情况下出现。要测试以确保您的服务器/网址已启用gzip
压缩,请使用此在线工具对其进行测试:
http://www.feedthebot.com/tools/gzip/
如果答案是肯定的,请继续将代码添加到Xcode中的Objective-C代码中。在代码中的这一行之后:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:120.0];
只需添加:
// Create a mutable copy of the immutable request and add more headers
NSMutableURLRequest *mutableRequest = [request mutableCopy];
//add gzip compression
[mutableRequest addValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
// Now set our request variable with an (immutable) copy of the altered request
request = [mutableRequest copy];
这会显着加快您的响应时间,并且您无需使用AFNetworking
进行小型NSURLRequest
或NSURLConnection
任务。
答案 6 :(得分:-1)
我不确定您的问题是什么,但以下代码对我来说可靠。
- (id)init
{
self.downloadQueue = [[NSOperationQueue alloc] init];
[self.downloadQueue setMaxConcurrentOperationCount:1];
}
- (void)doDownload:(NSURL *)url
{
[self.downloadQueue addOperation:[NSBlockOperation blockOperationWithBlock:^{
NSData *data =[NSData dataWithContentsOfURL:url];
dispatch_sync(dispatch_get_main_queue(), ^{
NSAutoreleasePool *mainQueuePool = [[NSAutoreleasePool alloc] init];
... update user interface ...
[mainQueuePool release];
});
}]];
}
答案 7 :(得分:-1)
我认为这是您设备中的问题。尝试朋友的其他设备。