代码之家  ›  专栏  ›  技术社区  ›  Joonas Trussmann

用于文件下载的nsurlconnection+nsmutabledata非常慢

  •  1
  • Joonas Trussmann  · 技术社区  · 16 年前

    基本上,我需要在我的应用程序中下载一大堆文件,我已经设置了一个队列,用一个nsurlconnection下载每个文件,并将服务器响应增量存储在一个nsmutabledata中,直到下载完成,然后将整个文件写入磁盘。

    相关部分如下:

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)_response {
        response = [_response retain];
        if([response expectedContentLength] < 1) {
            data = [[NSMutableData alloc] init];
        }
        else {
            data = [[NSMutableData dataWithCapacity:[response expectedContentLength]] retain];
        }
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)_data {
        [data appendData:_data];
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        NSLog(@"saved: %@", self.savePath);
        [data writeToFile:self.savePath atomically:YES];
    }
    

    有什么关于为什么这会非常缓慢的见解吗?模拟器的情况非常糟糕,在实际设备上情况更糟。我的最大下载容量大约是2兆字节,所以我认为把整个东西存储在内存中直到它完成不是一个坏主意。这最多可达20kb/s(通过直接的特别WiFi连接)。

    编辑:在我所有的测试案例中,我都会得到一个Content-Length头,所以在接收到每个响应位的情况下,不需要增加NSmutableData。

    编辑2: this 是鲨鱼给我的。

    编辑3:所以这就是我设置连接的方式

    NSMutableURLRequest *request = [[NSMutableURLRequest requestWithURL:[NSURL URLWithString:[@"http://xxx.xxx.xxx.xxx/index.php?service=" stringByAppendingString:service]]] retain];
    
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[[options JSONRepresentation] dataUsingEncoding:NSUTF8StringEncoding]];
    
    NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:self];
    [conn start];
    

    当然,我实际上没有一个硬编码的URL,请求和连接都是Downloader类的实例变量。没关系,但对于JSON,我正在使用 http://code.google.com/p/json-framework/ . 选项和服务都是方法参数(nsstring和nsdictionary),这两者都不重要。

    2 回复  |  直到 16 年前
        1
  •  2
  •   Joonas Trussmann    16 年前

    孩子,这很尴尬。结果发现我的Content-Length头不准确,这导致nsurlConnection需要等待某种类型的超时才能完成,即使它拥有所有的数据。真的有道理。也许这能帮助别人。

        2
  •  0
  •   TechZen    16 年前

    我会分析一下慢下来发生在哪里,以什么样的模式。放入LOG语句 connection:didReceiveData 查看它的调用频率。你在找:

    1. 调用方法之间的相对运行时间。
    2. 通话间隔时间是否随着应用程序的运行而增加。

    如果调用之间经过的时间是应用程序花费其大部分时间的地方,那么瓶颈就在请求本身。请求配置错误,或者服务器发送不快。

    如果通话间隔时间越长,应用程序的运行时间越长,则可能是内存问题。随着数据越来越大,内存也越来越有限,应用程序必须在内存中交换更多的东西,这会减慢所有操作的速度。要测试,请记录 didReciveMemoryWarning 任何活动对象中的方法。


    更新:

    根据Shark的说法,问题在于你的URL请求,而不是你发布的代码。您需要了解如何设置请求。

    推荐文章