使用AFNetworking下载多个文件时出现内存压力问题 [英] Memory pressure issue while downloading multiple files using AFNetworking

查看:85
本文介绍了使用AFNetworking下载多个文件时出现内存压力问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我试图下载数千张图像(每个图像最大3mb)和10幅视频(每个视频最大100mb)并将其保存在Documents Directory中。

In my application i am trying to download thousands of images (each image size with a maximum of 3mb) and 10's of videos (each video size with a maximum of 100mb) and saving it in Documents Directory.

要实现这一点,我正在使用AFNetworking

To achieve this i am using AFNetworking

在这里,我的问题是我正在获取所有数据当我使用慢速wifi(大约4mbps)时成功,但如果我在 wifi速度为100mbps 下进行相同的下载,则应用程序会得到下载图像时出现内存警告,下载视频然后应用程序崩溃时出现内存压力问题

Here my problem is i am getting all the data successfully when i am using a slow wifi (around 4mbps), but the same downloading if i am doing under a wifi with a speed of 100mbps the application is getting memory warning while downloading images and memory pressure issue while downloading videos and then application is crashing.

-(void) AddVideoIntoDocument :(NSString *)name :(NSString *)urlAddress{

    NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlAddress]];
    [theRequest setTimeoutInterval:1000.0];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:name];
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"Successfully downloaded file to %@", path);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];
    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {

        //NSLog(@"Download = %f", (float)totalBytesRead / totalBytesExpectedToRead);

    }];
    [operation start];
}

-(void)downloadRequestedImage : (NSString *)imageURL :(NSInteger) type :(NSString *)imgName{

    NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:imageURL]];
    [theRequest setTimeoutInterval:10000.0];
    AFHTTPRequestOperation *posterOperation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
    posterOperation.responseSerializer = [AFImageResponseSerializer serializer];
    [posterOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        //NSLog(@"Response: %@", responseObject);

        UIImage *secImg = responseObject;
        if(type == 1) { // Delete the image from DB
            [self removeImage:imgName];
        }
        [self AddImageIntoDocument:secImg :imgName];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Image request failed with error: %@", error);
    }];

    [posterOperation start];
}

上面的代码我根据视频数量循环播放我必须下载的图像

该行为背后的原因是什么

What is the reason behind that behaviour

我什至拥有两种情况下内存分配的屏幕截图

I even have screen shots of memory allocation for both the scenarios

请帮助

添加代码以保存下载的图像也

Adding code for saving the downloaded images also

-(void)AddImageIntoDocument :(UIImage *)img :(NSString *)str{

    if(img) {
        NSData *pngData = UIImageJPEGRepresentation(img, 0.4);
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

        NSString *filePathName =[[paths objectAtIndex:0]stringByAppendingPathComponent:str];
        [pngData writeToFile:filePathName atomically:YES];
    }
    else {
        NSLog(@"Network Error while downloading the image!!! Please try again.");
    }
}


推荐答案

出现这种情况的原因是,您正在将大文件加载到内存中(并且可能它发生得足够快,以至于您的应用程序没有机会响应内存压力通知)。

The reason for this behavior is that you're loading your large files into memory (and presumably it's happening quickly enough that you app isn't having a chance to respond to memory pressure notifications).

您可以通过不将这些下载内容加载到内存中来控制峰值内存使用量,从而减轻这种情况。下载大文件时,通常最好直接将其流式传输到持久性存储中。要使用AFNetworking做到这一点,您可以设置 AFURLConnectionOperation outputStream ,它应该直接将内容流式传输到文件,例如

You can mitigate this by controlling the peak memory usage by not loading these downloads into memory. When download large files, it's often better to stream them directly to persistent storage. To do this with AFNetworking, you can set the outputStream of the AFURLConnectionOperation, and it should stream the contents directly to that file, e.g.

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path          = [documentsPath stringByAppendingPathComponent:[url lastPathComponent]]; // use whatever path is appropriate for your app

operation.outputStream = [[NSOutputStream alloc] initToFileAtPath:path append:NO];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"successful");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"failure: %@", error);
}];

[self.downloadQueue addOperation:operation];






顺便说一句,不只是在这些请求上调用 start 。就个人而言,我总是将它们添加到已指定最大并发操作数的队列中:


BTW, you'll notice that I'm not just calling start on these requests. Personally, I always add them to a queue for which I've specified the maximum number of concurrent operations:

self.downloadQueue = [[NSOperationQueue alloc] init];
self.downloadQueue.maxConcurrentOperationCount = 4;
self.downloadQueue.name = @"com.domain.app.downloadQueue";

我认为这对内存使用的重要性不如直接将结果流传输到 outputStream 使用持久性存储,但是我发现这是在启动许多并发请求时管理系统资源的另一种机制。

I think this is less critical regarding memory usage than the streaming of the results directly to a outputStream using persistent storage, but I find this is another mechanism for managing system resources when initiating many concurrent requests.

这篇关于使用AFNetworking下载多个文件时出现内存压力问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆