NSURLConnection + NSMutableData для загрузки файлов очень медленно - PullRequest
1 голос
/ 20 июля 2010

В основном происходит то, что мне нужно загрузить целую кучу файлов в мое приложение, и я настроил своего рода очередь, которая загружает каждый файл с помощью 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 мегабайт, поэтому я решил, что хранение всего этого в памяти до его завершения не будет такой уж плохой идеей. В лучшем случае это составляет около 20 КБ / с (при прямом прямом Wi-Fi соединении).

Редактировать: во всех моих тестовых случаях я получаю заголовок Content-Length, поэтому не нужно увеличивать NSMutableData с каждым полученным битом ответа.

Редактировать 2: это это все, что Акула дает мне.

Редактировать 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-адреса, и оба запроса, и conn являются переменными экземпляра класса загрузчика. Не то чтобы это имело значение, но для JSON я использую http://code.google.com/p/json-framework/. Опции и сервис - это параметры метода (NSString и NSDictionary), но не так, чтобы они тоже имели значение.

Ответы [ 2 ]

2 голосов
/ 26 июля 2010

Мальчик это смущает. Оказывается, мой заголовок Content-Length был неточным, в результате чего NSURLConnection пришлось ждать некоторого тайм-аута, прежде чем он закончится, даже если в нем были все данные. Имеет смысл на самом деле. Может быть, это поможет кому-то еще.

0 голосов
/ 20 июля 2010

Я бы в профиле, чтобы узнать, где происходит замедление и в каком паттерне.Поместите оператор log в connection:didReceiveData, чтобы увидеть запись, как часто он вызывается.Вы ищете:

  1. Относительное время, прошедшее между вызовами метода.
  2. Увеличивается ли время между вызовами при запуске приложения.

Если истекшее время между вызовами является тем, где приложение проводит большую часть своего времени, то узким местом является сам запрос.Либо запрос неправильно настроен, либо сервер не отправляется быстро.

Если время между вызовами увеличивается, чем дольше работает приложение, то это, вероятно, проблема с памятью.По мере того, как объем данных увеличивается, а объем памяти становится все более ограниченным, приложению приходится обменивать больше информации в память и из нее, что замедляет все.Чтобы проверить, зарегистрируйте различные методы didReciveMemoryWarning в любых активных объектах.


Обновление:

По словам Акулы, проблема в вашем URL-запросе, а не в коде, который вы опубликовали.Вам нужно посмотреть, как вы настроили запрос.

...