Я внедряю приложение iOS, которое должно получать огромное количество изображений по HTTP. Я пробовал несколько подходов, но независимо от того, что я делаю, Instuments показывает постоянно увеличивающееся распределение памяти, и приложение рано или поздно падает, когда я запускаю его на устройстве. Нет никаких утечек, показанных инструментами.
До сих пор я пробовал следующие утверждения:
- Получение изображений с использованием синхронного NSURLConnection в NSOperation
- Получение изображений с использованием асинхронного NSURLConnection в NSOperation
- Извлеките изображения, используя [NSData dataWithContentsOfURL: url] в главном потоке
- Получение изображений с использованием синхронного ASIHTTPRequest в NSOperation
- Извлеките изображения с помощью асинхронного ASIHTTPRequest и добавьте его в NSOperationQueue
- Извлеките изображения с помощью асинхронного ASIHTTPRequest и с помощью функции завершенияBlock
Дерево вызовов в Instrumetns показывает, что память используется во время обработки HTTP-ответа. В случае асинхронного NSURLConnection это находится в
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
}
В случае синхронного NSURLConnection инструменты показывают растущую запись CFData (store). Проблема с ASIHTTPRequest кажется такой же, как и с асинхронным NSURLConnection в аналогичной кодовой позиции. Подход [NSData dataWithContentsOfURL: url] показывает все большее количество общего распределения памяти в этом утверждении.
Я использую NSAutoReleasePool, когда запрос выполняется в отдельном потоке, и я попытался освободить память с помощью [[NSURLCache sharedURLCache] removeAllCachedResponses] - без успеха.
Любые идеи/подсказки для решения проблемы? Спасибо.
Edit: Поведение появляется только в том случае, если я сохраняю изображения с помощью CoreData. Вот код, который я запускаю как NSInvocationOperation:
-(void) _fetchAndSave:(NSString*) imageId {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *url = [NSString stringWithFormat:@"%@%@", kImageUrl, imageId];
HTTPResponse *response = [SimpleHTTPClient GET:url headerOrNil:nil];
NSData *data = [response payload];
if(data && [data length] > 0) {
UIImage *thumbnailImage = [UIImage imageWithData:data];
NSData *thumbnailData = UIImageJPEGRepresentation([thumbnailImage scaleToSize:CGSizeMake(55, 53)], 0.5); // UIImagePNGRepresentation(thumbnail);
[self performSelectorOnMainThread:@selector(_save:) withObject:[NSArray arrayWithObjects:imageId, data, thumbnailData, nil] waitUntilDone:NO];
}
[pool release];
}
Все связанные с CoreData вещи выполняются в Main-Thread здесь, поэтому не должно быть многопоточности CoreData. Однако, если я сохраняю изображения, приборы показывают постоянное увеличение выделения памяти в положениях, описанных выше.
Изменить II:
Код, связанный с CoreData:
-(void) _save:(NSArray*)args {
NSString *imageId = [args objectAtIndex:0];
NSData *data = [args objectAtIndex:1];
NSData *thumbnailData = [args objectAtIndex:2];
Image *image = (Image*)[[CoreDataHelper sharedSingleton] createObject:@Image];
image.timestamp = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
image.data = data;
Thumbnail *thumbnail = (Thumbnail*)[[CoreDataHelper sharedSingleton] createObject:@"Thumbnail"];
thumbnail.data = thumbnailData;
thumbnail.timestamp = image.timestamp;
[[CoreDataHelper sharedSingleton] save];
}
Из CoreDataHelper (self.managedObjectContext выбирает NSManagedObjectContext, который можно использовать в текущем потоке):
-(NSManagedObject *) createObject:(NSString *) entityName {
return [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.managedObjectContext];
}